Drupal Behaviors Integration
When to Use
Use this when you need to run JavaScript behaviors on content loaded via HTMX, or clean up when content is removed.
Decision
| Event | When fires | Purpose |
|---|---|---|
htmx:drupal:load |
After settle AND asset loading complete | Attach behaviors to new content |
htmx:drupal:unload |
Before content removal | Detach behaviors from removed content |
Behaviors automatically work with HTMX content — htmx:drupal:load triggers Drupal.attachBehaviors().
Pattern
Standard Drupal behavior (works automatically with HTMX):
Drupal.behaviors.myModuleBehavior = {
attach(context, settings) {
// context is the HTMX-loaded content
// Runs after htmx:drupal:load fires
console.log('Attached to:', context);
},
detach(context, settings, trigger) {
if (trigger === 'unload') {
console.log('Cleaning up:', context);
}
}
};
Listening to HTMX lifecycle events:
htmx.on('htmx:beforeRequest', (event) => {
console.log('Starting request to:', event.detail.path);
});
htmx.on('htmx:afterSwap', (event) => {
console.log('Content swapped:', event.detail.elt);
});
htmx.on('htmx:drupal:load', (event) => {
console.log('Drupal processing complete:', event.detail.elt);
});
Preventing double-processing (HTMX processes elements inserted by traditional AJAX):
Drupal.behaviors.htmx = {
attach(context) {
if (!attachFromHtmx && context !== document) {
htmx.process(context);
}
}
};
Common Mistakes
- Wrong: Expecting behaviors to run immediately after swap → Right: Behaviors run AFTER
htmx:drupal:load, which fires only after all assets load - Wrong: Forgetting to implement
detach()→ Right: Memory leaks when event handlers aren't cleaned up - Wrong: Not checking trigger type in
detach()→ Right: Usetrigger === 'unload'to identify HTMX removals
See Also
- Response Headers
- Asset Loading
- Reference:
/core/misc/htmx/htmx-behaviors.js - Reference: Drupal JavaScript API Overview
- Reference: HTMX Events Documentation