# 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
``` ## URL-Templates ### Einfaches Template ```javascript // Handler-Konfiguration const myHandler = { urlTemplate: '/api/users/{id}/{action}', method: 'POST' }; // HTML // Wird zu: /api/users/123/delete ``` ### Template mit mehreren Parametern ```javascript // Handler-Konfiguration const myHandler = { urlTemplate: '/api/{entity}/{id}/{action}', method: 'POST' }; // HTML // 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 // 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 `` 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 ``` ## Loading States ### Handler-basierte Loading-Texte ```javascript const myHandler = { loadingTexts: { start: 'Starting...', stop: 'Stopping...', delete: 'Deleting...' } }; ``` ### Element-basierte Loading-Texte ```html ``` ## 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 ``` ## 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 ``` ## Spezielle Action-Typen ### Window-Actions (öffnen in neuem Tab) ```html ``` ## 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 ``` ### Bulk Operations ```html ``` ## 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
``` ```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 ``` ### Beispiel 3: Action mit mehreren Parametern ```html ``` ```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