# HTMX Templates and Patterns This directory contains HTMX-specific templates and components for ThrillWiki. ## Overview HTMX is used throughout ThrillWiki for dynamic content updates without full page reloads. This guide documents the standardized patterns and conventions. ## Directory Structure ``` htmx/ ├── components/ # Reusable HTMX components │ ├── confirm_dialog.html # Confirmation modal │ ├── error_message.html # Error display │ ├── filter_badge.html # Filter tag/badge │ ├── inline_edit_field.html # Inline editing │ ├── loading_indicator.html # Loading spinners │ └── success_toast.html # Success notification ├── partials/ # HTMX response partials └── README.md # This documentation ``` ## Swap Strategies Use consistent swap strategies across the application: | Strategy | Use Case | Example | |----------|----------|---------| | `innerHTML` | Replace content inside container | List updates, search results | | `outerHTML` | Replace entire element | Status badges, table rows | | `beforeend` | Append items | Infinite scroll, new items | | `afterbegin` | Prepend items | New items at top of list | ### Examples ```html
``` ## Target Naming Conventions Follow these naming patterns for `hx-target`: | Pattern | Use Case | Example | |---------|----------|---------| | `#object-type-id` | Specific objects | `#park-123`, `#ride-456` | | `#section-name` | Page sections | `#results`, `#filters`, `#stats` | | `#modal-container` | Modal content | `#modal-container` | | `this` | Self-replacement | Status badges, inline edits | ### Examples ```html
Content
{% include 'htmx/components/loading_indicator.html' with id='loading' message='Loading...' %}
Content {% include 'htmx/components/loading_indicator.html' with id='overlay' mode='overlay' %}
``` ## Error Handling HTMX errors are handled globally in `base.html`. The system: 1. Shows toast notifications for different HTTP status codes 2. Handles timeouts (30 second default) 3. Handles network errors 4. Supports retry logic ### Custom Error Responses Return error templates for 4xx/5xx responses: ```html {% include 'htmx/components/error_message.html' with title='Error' message='Something went wrong.' %} ``` ## Toast Notifications via HTMX Trigger toast notifications from server responses: ```python from django.http import JsonResponse def my_view(request): response = render(request, 'partial.html') response['HX-Trigger'] = json.dumps({ 'showToast': { 'type': 'success', # success, error, warning, info 'message': 'Action completed!', 'duration': 5000 # optional, in milliseconds } }) return response ``` ## Form Validation Use inline HTMX validation for forms: ```html
``` Validation endpoint returns: ```html {% include 'forms/partials/field_success.html' with message='Username available' %} {% include 'forms/partials/field_error.html' with errors=errors %} ``` ## Common Patterns ### Search with Debounce ```html ``` ### Modal Content Loading ```html ``` ### Infinite Scroll ```html
{% for item in items %} {% include 'item.html' %} {% endfor %} {% if page_obj.has_next %}
{% include 'htmx/components/loading_indicator.html' %}
{% endif %}
``` ### Status Badge Refresh ```html {% include 'components/status_badge.html' with status=park.status %} ``` ## Best Practices 1. **Always specify `hx-swap`** even for default behavior (clarity) 2. **Use meaningful target IDs** following naming conventions 3. **Include loading indicators** for all async operations 4. **Handle errors gracefully** with user-friendly messages 5. **Debounce search/filter inputs** to reduce server load 6. **Use `hx-push-url`** for URL changes that should be bookmarkable 7. **Provide fallback** for JavaScript-disabled browsers where possible ## Security Considerations - CSRF tokens are automatically included via `hx-headers` in base.html - All HTMX endpoints should validate permissions - Use Django's `@require_http_methods` decorator - Sanitize any user input before rendering ## Debugging Enable HTMX debugging in development: ```javascript htmx.logAll(); ``` Check browser DevTools Network tab for HTMX requests (look for `HX-Request: true` header).