12 KiB
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 ausdata-action-param-id{param:name}- Parameter ausdata-action-param-{name}{data:name}- Wert ausdata-{name}Attribut
Basis-Verwendung
1. ActionHandler initialisieren
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
<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
// 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
// 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
// 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):
data-csrf-tokenAttribut des Action-Elementsdata-csrf-tokenAttribut des nächstgelegenen[data-live-component]Elementsdata-csrf-tokenAttribut des Containers- Meta-Tag
<meta name="csrf-token"> - Fallback: Leerer String
Das Token wird automatisch hinzugefügt:
- Header:
X-CSRF-Token - Body:
_tokenund_form_id
Bestätigungen
Handler-basierte Bestätigungen
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
<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
const myHandler = {
loadingTexts: {
start: 'Starting...',
stop: 'Stopping...',
delete: 'Deleting...'
}
};
Element-basierte Loading-Texte
<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
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
<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
// 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
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
<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)
<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:
// Gut
const handler = new ActionHandler('.docker-containers-component');
// Schlecht
const handler = new ActionHandler('body');
2. Handler wiederverwenden
Erstelle wiederverwendbare Handler für ähnliche Actions:
// Gut: Wiederverwendbarer Handler
const userHandler = {
urlTemplate: '/api/users/{id}/{action}',
// ...
};
// Schlecht: Inline-Konfiguration für jede Action
3. Konsistente Namenskonventionen
Verwende konsistente Action-Namen:
// 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:
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
<button
data-action="start"
data-action-handler="docker-container"
data-action-param-id="{{containerId}}"
>
Start
</button>
Bulk Operations
<button
data-action="delete"
data-action-handler="bulk-operations"
data-action-param-entity="users"
>
Delete Selected
</button>
API-Referenz
ActionHandler Konstruktor
new ActionHandler(containerSelector, options)
Parameter:
containerSelector(string): CSS-Selektor für Container-Elementoptions(object): KonfigurationsoptionencsrfTokenSelector(string): Selektor für CSRF-Token ElementtoastHandler(function): Funktion für Toast-AnzeigeconfirmationHandler(function): Funktion für BestätigungenloadingTexts(object): Mapping von Action-Namen zu Loading-TextenautoRefresh(boolean): Automatisches Refresh nach erfolgreicher ActionrefreshHandler(function): Funktion für Refresh
registerHandler
handler.registerHandler(name, config)
Parameter:
name(string): Handler-Nameconfig(object): Handler-KonfigurationurlTemplate(string): URL-Template mit Platzhalternmethod(string): HTTP-Methode (default: POST)confirmations(object): Bestätigungs-Nachrichten pro ActionloadingTexts(object): Loading-Texte pro ActionsuccessMessages(object): Success-Messages pro ActionerrorMessages(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
<div class="user-actions">
<button
data-action="delete"
data-action-handler="user-handler"
data-action-param-id="123"
>
Delete User
</button>
</div>
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
<button
data-action="custom"
data-action-url="/api/custom-endpoint"
data-action-method="PUT"
>
Custom Action
</button>
Beispiel 3: Action mit mehreren Parametern
<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>
handler.registerHandler('transfer-handler', {
urlTemplate: '/api/transfer/{param:from}/{param:to}/{param:amount}',
method: 'POST'
});
Troubleshooting
Actions werden nicht ausgeführt
- Prüfe, ob Container-Selektor korrekt ist
- Prüfe, ob
data-actionAttribut vorhanden ist - Prüfe Browser-Konsole für Warnungen
- Prüfe, ob Handler registriert ist
CSRF-Token-Fehler
- Prüfe, ob CSRF-Token-Element vorhanden ist
- Prüfe, ob
csrfTokenSelectorkorrekt ist - Prüfe, ob Token im HTML vorhanden ist
URL-Template wird nicht ersetzt
- Prüfe, ob Platzhalter korrekt geschrieben sind (
{id}, nicht{ id }) - Prüfe, ob Parameter-Attribute vorhanden sind (
data-action-param-id) - Prüfe Browser-Konsole für Warnungen
Toast wird nicht angezeigt
- Prüfe, ob
toastHandlerkonfiguriert ist - Prüfe, ob
LiveComponentUIHelperverfügbar ist - Prüfe Browser-Konsole für Fehler