Some checks failed
Deploy Application / deploy (push) Has been cancelled
524 lines
12 KiB
Markdown
524 lines
12 KiB
Markdown
# ActionHandler Guide
|
|
|
|
## Übersicht
|
|
|
|
Das `ActionHandler` Modul bietet ein wiederverwendbares Pattern für Event-Delegation-basiertes Action-Handling mit automatischem CSRF-Token-Handling, Loading States, Bestätigungen und Toast-Integration.
|
|
|
|
## Konzepte
|
|
|
|
### Event Delegation
|
|
|
|
Statt jedem Button einen eigenen Event Listener zuzuweisen, verwendet ActionHandler Event Delegation: Ein einziger Event Listener auf dem Container-Element behandelt alle Actions.
|
|
|
|
**Vorteile:**
|
|
- Bessere Performance (weniger Event Listener)
|
|
- Funktioniert mit dynamisch hinzugefügten Elementen
|
|
- Einfacheres Code-Management
|
|
|
|
### Handler-Registry
|
|
|
|
Handler sind vorkonfigurierte Action-Patterns, die wiederverwendet werden können. Sie definieren:
|
|
- URL-Templates
|
|
- Bestätigungs-Nachrichten
|
|
- Loading-Texte
|
|
- Success/Error-Messages
|
|
|
|
### URL-Templates
|
|
|
|
URL-Templates verwenden Platzhalter, die zur Laufzeit ersetzt werden:
|
|
- `{action}` - Der Action-Name
|
|
- `{id}` - ID aus `data-action-param-id`
|
|
- `{param:name}` - Parameter aus `data-action-param-{name}`
|
|
- `{data:name}` - Wert aus `data-{name}` Attribut
|
|
|
|
## Basis-Verwendung
|
|
|
|
### 1. ActionHandler initialisieren
|
|
|
|
```javascript
|
|
import { ActionHandler } from '/assets/js/modules/common/ActionHandler.js';
|
|
import { dockerContainerHandler } from '/assets/js/modules/common/ActionHandlers.js';
|
|
|
|
const handler = new ActionHandler('.my-container', {
|
|
csrfTokenSelector: '[data-live-component]',
|
|
toastHandler: showToast,
|
|
refreshHandler: refreshComponent,
|
|
autoRefresh: true
|
|
});
|
|
|
|
// Handler registrieren
|
|
handler.registerHandler('docker-container', dockerContainerHandler);
|
|
```
|
|
|
|
### 2. HTML mit data-* Attributen
|
|
|
|
```html
|
|
<div class="my-container">
|
|
<button
|
|
data-action="start"
|
|
data-action-handler="docker-container"
|
|
data-action-param-id="container-123"
|
|
>
|
|
Start Container
|
|
</button>
|
|
|
|
<button
|
|
data-action="stop"
|
|
data-action-handler="docker-container"
|
|
data-action-param-id="container-123"
|
|
>
|
|
Stop Container
|
|
</button>
|
|
</div>
|
|
```
|
|
|
|
## URL-Templates
|
|
|
|
### Einfaches Template
|
|
|
|
```javascript
|
|
// Handler-Konfiguration
|
|
const myHandler = {
|
|
urlTemplate: '/api/users/{id}/{action}',
|
|
method: 'POST'
|
|
};
|
|
|
|
// HTML
|
|
<button
|
|
data-action="delete"
|
|
data-action-handler="my-handler"
|
|
data-action-param-id="123"
|
|
>
|
|
Delete User
|
|
</button>
|
|
|
|
// Wird zu: /api/users/123/delete
|
|
```
|
|
|
|
### Template mit mehreren Parametern
|
|
|
|
```javascript
|
|
// Handler-Konfiguration
|
|
const myHandler = {
|
|
urlTemplate: '/api/{entity}/{id}/{action}',
|
|
method: 'POST'
|
|
};
|
|
|
|
// HTML
|
|
<button
|
|
data-action="update"
|
|
data-action-handler="my-handler"
|
|
data-action-param-entity="users"
|
|
data-action-param-id="123"
|
|
>
|
|
Update User
|
|
</button>
|
|
|
|
// Wird zu: /api/users/123/update
|
|
```
|
|
|
|
### Template mit {data:*} Platzhaltern
|
|
|
|
```javascript
|
|
// Handler-Konfiguration
|
|
const myHandler = {
|
|
urlTemplate: '/api/{data:entity}/{data:id}/{action}',
|
|
method: 'POST'
|
|
};
|
|
|
|
// HTML
|
|
<button
|
|
data-action="delete"
|
|
data-action-handler="my-handler"
|
|
data-entity="users"
|
|
data-id="123"
|
|
>
|
|
Delete
|
|
</button>
|
|
|
|
// Wird zu: /api/users/123/delete
|
|
```
|
|
|
|
## CSRF-Token Handling
|
|
|
|
ActionHandler extrahiert CSRF-Token automatisch aus verschiedenen Quellen (in Reihenfolge):
|
|
|
|
1. `data-csrf-token` Attribut des Action-Elements
|
|
2. `data-csrf-token` Attribut des nächstgelegenen `[data-live-component]` Elements
|
|
3. `data-csrf-token` Attribut des Containers
|
|
4. Meta-Tag `<meta name="csrf-token">`
|
|
5. Fallback: Leerer String
|
|
|
|
Das Token wird automatisch hinzugefügt:
|
|
- Header: `X-CSRF-Token`
|
|
- Body: `_token` und `_form_id`
|
|
|
|
## Bestätigungen
|
|
|
|
### Handler-basierte Bestätigungen
|
|
|
|
```javascript
|
|
const myHandler = {
|
|
urlTemplate: '/api/users/{id}/{action}',
|
|
confirmations: {
|
|
delete: 'Are you sure you want to delete this user?',
|
|
update: 'Are you sure you want to update this user?'
|
|
}
|
|
};
|
|
```
|
|
|
|
### Element-basierte Bestätigungen
|
|
|
|
```html
|
|
<button
|
|
data-action="delete"
|
|
data-action-confirm="Are you sure?"
|
|
data-action-handler="my-handler"
|
|
data-action-param-id="123"
|
|
>
|
|
Delete
|
|
</button>
|
|
```
|
|
|
|
## Loading States
|
|
|
|
### Handler-basierte Loading-Texte
|
|
|
|
```javascript
|
|
const myHandler = {
|
|
loadingTexts: {
|
|
start: 'Starting...',
|
|
stop: 'Stopping...',
|
|
delete: 'Deleting...'
|
|
}
|
|
};
|
|
```
|
|
|
|
### Element-basierte Loading-Texte
|
|
|
|
```html
|
|
<button
|
|
data-action="delete"
|
|
data-action-loading-text="Deleting user..."
|
|
data-action-handler="my-handler"
|
|
data-action-param-id="123"
|
|
>
|
|
Delete
|
|
</button>
|
|
```
|
|
|
|
## Toast-Integration
|
|
|
|
### Handler-basierte Toast-Messages
|
|
|
|
```javascript
|
|
const myHandler = {
|
|
successMessages: {
|
|
delete: 'User deleted successfully',
|
|
update: 'User updated successfully'
|
|
},
|
|
errorMessages: {
|
|
delete: 'Failed to delete user',
|
|
update: 'Failed to update user'
|
|
}
|
|
};
|
|
```
|
|
|
|
### Element-basierte Toast-Messages
|
|
|
|
```html
|
|
<button
|
|
data-action="delete"
|
|
data-action-success-toast="User deleted!"
|
|
data-action-error-toast="Failed to delete user"
|
|
data-action-handler="my-handler"
|
|
data-action-param-id="123"
|
|
>
|
|
Delete
|
|
</button>
|
|
```
|
|
|
|
## Custom Handler erstellen
|
|
|
|
### 1. Handler-Konfiguration erstellen
|
|
|
|
```javascript
|
|
// resources/js/modules/common/ActionHandlers.js
|
|
export const myCustomHandler = {
|
|
urlTemplate: '/api/{entity}/{id}/{action}',
|
|
method: 'POST',
|
|
confirmations: {
|
|
delete: 'Are you sure?'
|
|
},
|
|
loadingTexts: {
|
|
delete: 'Deleting...',
|
|
update: 'Updating...'
|
|
},
|
|
successMessages: {
|
|
delete: 'Deleted successfully',
|
|
update: 'Updated successfully'
|
|
},
|
|
errorMessages: {
|
|
delete: 'Failed to delete',
|
|
update: 'Failed to update'
|
|
}
|
|
};
|
|
```
|
|
|
|
### 2. Handler registrieren
|
|
|
|
```javascript
|
|
import { ActionHandler } from '/assets/js/modules/common/ActionHandler.js';
|
|
import { myCustomHandler } from '/assets/js/modules/common/ActionHandlers.js';
|
|
|
|
const handler = new ActionHandler('.my-container');
|
|
handler.registerHandler('my-handler', myCustomHandler);
|
|
```
|
|
|
|
### 3. Handler verwenden
|
|
|
|
```html
|
|
<button
|
|
data-action="delete"
|
|
data-action-handler="my-handler"
|
|
data-action-param-entity="users"
|
|
data-action-param-id="123"
|
|
>
|
|
Delete User
|
|
</button>
|
|
```
|
|
|
|
## Spezielle Action-Typen
|
|
|
|
### Window-Actions (öffnen in neuem Tab)
|
|
|
|
```html
|
|
<button
|
|
data-action="logs"
|
|
data-action-type="window"
|
|
data-action-url="/api/containers/{id}/logs"
|
|
data-action-param-id="123"
|
|
>
|
|
View Logs
|
|
</button>
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Container-Selektor verwenden
|
|
|
|
Verwende einen spezifischen Container-Selektor, um Konflikte zu vermeiden:
|
|
|
|
```javascript
|
|
// Gut
|
|
const handler = new ActionHandler('.docker-containers-component');
|
|
|
|
// Schlecht
|
|
const handler = new ActionHandler('body');
|
|
```
|
|
|
|
### 2. Handler wiederverwenden
|
|
|
|
Erstelle wiederverwendbare Handler für ähnliche Actions:
|
|
|
|
```javascript
|
|
// Gut: Wiederverwendbarer Handler
|
|
const userHandler = {
|
|
urlTemplate: '/api/users/{id}/{action}',
|
|
// ...
|
|
};
|
|
|
|
// Schlecht: Inline-Konfiguration für jede Action
|
|
```
|
|
|
|
### 3. Konsistente Namenskonventionen
|
|
|
|
Verwende konsistente Action-Namen:
|
|
|
|
```javascript
|
|
// Gut: RESTful Actions
|
|
start, stop, restart, delete, update, create
|
|
|
|
// Schlecht: Inkonsistente Namen
|
|
startContainer, stopContainer, deleteUser, updateUserData
|
|
```
|
|
|
|
### 4. Error Handling
|
|
|
|
ActionHandler behandelt Errors automatisch, aber du kannst Custom Error-Handling hinzufügen:
|
|
|
|
```javascript
|
|
const handler = new ActionHandler('.container', {
|
|
toastHandler: (message, type) => {
|
|
if (type === 'error') {
|
|
// Custom Error-Logging
|
|
console.error('[ActionHandler]', message);
|
|
}
|
|
// Standard Toast
|
|
showToast(message, type);
|
|
}
|
|
});
|
|
```
|
|
|
|
## Integration in bestehende Komponenten
|
|
|
|
### Docker Container Actions
|
|
|
|
```html
|
|
<button
|
|
data-action="start"
|
|
data-action-handler="docker-container"
|
|
data-action-param-id="{{containerId}}"
|
|
>
|
|
Start
|
|
</button>
|
|
```
|
|
|
|
### Bulk Operations
|
|
|
|
```html
|
|
<button
|
|
data-action="delete"
|
|
data-action-handler="bulk-operations"
|
|
data-action-param-entity="users"
|
|
>
|
|
Delete Selected
|
|
</button>
|
|
```
|
|
|
|
## API-Referenz
|
|
|
|
### ActionHandler Konstruktor
|
|
|
|
```javascript
|
|
new ActionHandler(containerSelector, options)
|
|
```
|
|
|
|
**Parameter:**
|
|
- `containerSelector` (string): CSS-Selektor für Container-Element
|
|
- `options` (object): Konfigurationsoptionen
|
|
- `csrfTokenSelector` (string): Selektor für CSRF-Token Element
|
|
- `toastHandler` (function): Funktion für Toast-Anzeige
|
|
- `confirmationHandler` (function): Funktion für Bestätigungen
|
|
- `loadingTexts` (object): Mapping von Action-Namen zu Loading-Texten
|
|
- `autoRefresh` (boolean): Automatisches Refresh nach erfolgreicher Action
|
|
- `refreshHandler` (function): Funktion für Refresh
|
|
|
|
### registerHandler
|
|
|
|
```javascript
|
|
handler.registerHandler(name, config)
|
|
```
|
|
|
|
**Parameter:**
|
|
- `name` (string): Handler-Name
|
|
- `config` (object): Handler-Konfiguration
|
|
- `urlTemplate` (string): URL-Template mit Platzhaltern
|
|
- `method` (string): HTTP-Methode (default: POST)
|
|
- `confirmations` (object): Bestätigungs-Nachrichten pro Action
|
|
- `loadingTexts` (object): Loading-Texte pro Action
|
|
- `successMessages` (object): Success-Messages pro Action
|
|
- `errorMessages` (object): Error-Messages pro Action
|
|
|
|
### HTML-Attribute
|
|
|
|
- `data-action`: Action-Name (erforderlich)
|
|
- `data-action-handler`: Handler-Name (optional)
|
|
- `data-action-url`: Direkte URL (optional, überschreibt Template)
|
|
- `data-action-method`: HTTP-Methode (optional, default: POST)
|
|
- `data-action-confirm`: Bestätigungs-Nachricht (optional)
|
|
- `data-action-loading-text`: Loading-Text (optional)
|
|
- `data-action-success-toast`: Success-Message (optional)
|
|
- `data-action-error-toast`: Error-Message (optional)
|
|
- `data-action-type`: Action-Typ (optional, z.B. "window")
|
|
- `data-action-param-*`: Parameter für URL-Template (optional)
|
|
|
|
## Beispiele
|
|
|
|
### Beispiel 1: Einfache Action
|
|
|
|
```html
|
|
<div class="user-actions">
|
|
<button
|
|
data-action="delete"
|
|
data-action-handler="user-handler"
|
|
data-action-param-id="123"
|
|
>
|
|
Delete User
|
|
</button>
|
|
</div>
|
|
```
|
|
|
|
```javascript
|
|
import { ActionHandler } from '/assets/js/modules/common/ActionHandler.js';
|
|
|
|
const handler = new ActionHandler('.user-actions');
|
|
handler.registerHandler('user-handler', {
|
|
urlTemplate: '/api/users/{id}/{action}',
|
|
confirmations: {
|
|
delete: 'Are you sure?'
|
|
}
|
|
});
|
|
```
|
|
|
|
### Beispiel 2: Action mit Custom URL
|
|
|
|
```html
|
|
<button
|
|
data-action="custom"
|
|
data-action-url="/api/custom-endpoint"
|
|
data-action-method="PUT"
|
|
>
|
|
Custom Action
|
|
</button>
|
|
```
|
|
|
|
### Beispiel 3: Action mit mehreren Parametern
|
|
|
|
```html
|
|
<button
|
|
data-action="transfer"
|
|
data-action-handler="transfer-handler"
|
|
data-action-param-from="account-1"
|
|
data-action-param-to="account-2"
|
|
data-action-param-amount="100"
|
|
>
|
|
Transfer
|
|
</button>
|
|
```
|
|
|
|
```javascript
|
|
handler.registerHandler('transfer-handler', {
|
|
urlTemplate: '/api/transfer/{param:from}/{param:to}/{param:amount}',
|
|
method: 'POST'
|
|
});
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Actions werden nicht ausgeführt
|
|
|
|
1. Prüfe, ob Container-Selektor korrekt ist
|
|
2. Prüfe, ob `data-action` Attribut vorhanden ist
|
|
3. Prüfe Browser-Konsole für Warnungen
|
|
4. Prüfe, ob Handler registriert ist
|
|
|
|
### CSRF-Token-Fehler
|
|
|
|
1. Prüfe, ob CSRF-Token-Element vorhanden ist
|
|
2. Prüfe, ob `csrfTokenSelector` korrekt ist
|
|
3. Prüfe, ob Token im HTML vorhanden ist
|
|
|
|
### URL-Template wird nicht ersetzt
|
|
|
|
1. Prüfe, ob Platzhalter korrekt geschrieben sind (`{id}`, nicht `{ id }`)
|
|
2. Prüfe, ob Parameter-Attribute vorhanden sind (`data-action-param-id`)
|
|
3. Prüfe Browser-Konsole für Warnungen
|
|
|
|
### Toast wird nicht angezeigt
|
|
|
|
1. Prüfe, ob `toastHandler` konfiguriert ist
|
|
2. Prüfe, ob `LiveComponentUIHelper` verfügbar ist
|
|
3. Prüfe Browser-Konsole für Fehler
|
|
|