Alpine AJAX

repository·main·Indexed 22 days ago

https://github.com/imacrayon/alpine-ajax

An Alpine.js plugin for building server-powered frontends. It provides a set of directives that transform standard HTML forms and links into asynchronous AJAX-powered components, allowing developers to fetch and render HTML responses directly into the page without full reloads. It is designed as a lightweight (3kB) alternative to libraries like HTMX, Hotwired Turbo, and Unpoly, emphasizing convention over configuration and progressive enhancement.

Tokens
18.3K
Snippets
53
Records
65
Agent score
78%

What's inside alpine-ajax

  1. What is Alpine AJAX

    main
    Alpine AJAX is a set of AlpineJS directives designed to enable HTML forms and links to perform asynchronous HTTP requests. Instead of full page reloads, it allows you to fetch responses and render them directly into the page, facilitating a more dynamic user experience within an AlpineJS application.
  2. Use x-merge.transition for smooth content updates

    main

    When replacing content in a target element, you can use x-merge.transition to enable smoother transitions, such as those using the CSS View Transitions API. This attribute should be applied to both the existing container and the incoming content to signal that the replacement should be treated as a transition.

    <!-- On the existing element -->
    <div id="contact_1" x-merge.transition>
      ... 
    </div>
    
    <!-- On the incoming element (e.g., the form) -->
    <form id="contact_1" x-target x-merge.transition method="put" action="/contacts/1">
      ... 
    </form>
  3. Compare Alpine AJAX with Laravel Livewire

    main

    Livewire is a component-based framework specifically for Laravel, while Alpine AJAX is a general-purpose tool.

    • Architecture: Livewire requires a departure from standard Laravel conventions to follow its component-based model. Alpine AJAX is server-agnostic and can be added to an existing Laravel app as a progressive enhancement.
    • Progressive Enhancement: Livewire apps become unresponsive if JavaScript is unavailable. Alpine AJAX gracefully degrades, ensuring that links and forms continue to function as standard server-rendered elements even without JavaScript.
    • Bundle Size: Alpine AJAX is 3kB, while Livewire's JS bundle is 43kB.
  4. Comparing x-autofocus and x-merge="morph" for focus management

    main
    While x-merge="morph" can be used to preserve keyboard focus by attempting to morph the new content into the existing DOM, x-autofocus is often more predictable. Use x-autofocus in scenarios where the DOM transformation is significant enough that the Morph algorithm might fail to reliably preserve the focus state.
  5. Compare Alpine AJAX with Unpoly

    main

    Unpoly is a comprehensive frontend framework that includes built-in elements like loaders, modals, and popovers. Alpine AJAX is a lightweight 'drop-in' library.

    • Complexity: Unpoly requires learning novel concepts like 'fragments' and 'layers'. Alpine AJAX is simpler to integrate into existing projects.
    • Syntax: Unpoly uses an imperative API, whereas Alpine AJAX leverages the terse, declarative syntax of Alpine.js.
    • Bundle Size: Alpine AJAX (combined with Alpine.js) is roughly 18kB, whereas Unpoly is 43kB of JS plus 1kB of CSS.
  6. Use x-sync to update elements outside the target area

    main

    The x-sync attribute allows you to update specific elements on a page whenever the server sends a matching element in a response, even if those elements are not the primary target of the AJAX request (x-target).

    To use x-sync:

    1. Add the x-sync attribute to an element.
    2. Ensure the element has a unique id.
    3. When the server responds with an element containing the same id, the existing element on the client will be replaced by the new one.

    This is ideal for updating UI components that live in a base layout or persistent sidebar, such as unread message counters, notification flashes, or shopping cart totals, which are not part of the main content area being swapped.

    <div role="status">
      <ul x-sync id="notifications"></ul>
    </div>
  7. Compare Alpine AJAX with Hotwired Turbo

    main

    While both libraries enable AJAX-driven updates, Alpine AJAX offers several advantages in terms of simplicity and compatibility:

    • Server Requirements: Turbo requires specific response status codes, headers, and content (often requiring different templates for 'Turbo Requests' vs regular requests). Alpine AJAX only requires the server to respond with HTML and makes no distinction between AJAX and regular HTTP requests.
    • HTML Compatibility: Turbo uses Custom Elements (like <turbo-frame>), which can break standard HTML structures like tables. Alpine AJAX uses HTML attributes to define behavior, allowing it to be safely applied to any HTML element, including tables.
    • Communication: Turbo uses 'Turbo Streams' for updates. Alpine AJAX uses custom JavaScript events that can be mixed into any standard HTML response.
    • Bundle Size: Alpine AJAX is much smaller at 3kB compared to Turbo's 22kB.

    When to choose Turbo: If you are building a Ruby on Rails application and intend to transform your website into a native mobile application (Android/iOS) using the Hotwire workflow.

  8. Use x-target for form responses in dialogs

    main

    When a form is submitted via AJAX, applying the x-target attribute to the <form> element ensures that the server's response (whether it is a success message, a re-rendered form for validation errors, or a confirmation) is injected into the specified target element. This is particularly useful for keeping the user within the context of a modal window during the entire submission lifecycle.

    <form id="contact" x-target method="put" action="/contacts/1">
      <!-- Response will be rendered here -->
    </form>
  9. Compare Alpine AJAX with HTMX

    main

    Alpine AJAX and HTMX are both server-agnostic and compatible with Alpine.js. However, they differ in philosophy and size:

    • Philosophy: HTMX is highly flexible and unopinionated, providing low-level tooling. Alpine AJAX follows a convention over configuration approach, providing more guidance to help developers avoid common accessibility and progressive enhancement pitfalls.
    • Integration: Alpine AJAX is designed specifically as an Alpine.js plugin, making it feel more natural for developers already using the Alpine.js ecosystem.
    • Bundle Size: Alpine AJAX is significantly lighter at 3kB compared to HTMX's 13kB.
  10. Implement Progressive Enhancement with Alpine AJAX

    main
    When using Alpine AJAX, follow the principle of Progressive Enhancement. Build your UI using standard HTML links and forms first, ensuring the website is fully functional without any JavaScript. Once the core functionality is established, add Alpine AJAX attributes to intercept these interactions. This ensures that if JavaScript is unavailable or fails to load, your links and forms will still work as standard browser requests, providing a graceful degradation of service.
  11. Mock server for creating demos and prototypes

    main

    When building quick prototypes or demonstrating bugs without a real backend, you can use the included mock server script. This script provides a global route helper function that allows you to intercept AJAX requests on the frontend and return mocked HTML responses.

    Setup

    1. Include the Alpine AJAX CDN script.
    2. Include the Alpine.js CDN script.
    3. Include the Alpine AJAX mock server script (dist/server.js).
    4. Define your routes using the route(method, url, callback) function.

    Usage

    The route function takes a HTTP method, a URL pattern, and a callback. The callback receives a request object containing the form data or request parameters. You must return a string of HTML which will be used as the response for the AJAX request.

    Warning: The mock server is intended for demos and testing only. Do not use it in production environments.

    <!-- 1. Include required scripts -->
    <script defer src="https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@{{ APLINE_AJAX_VERSION }}/dist/cdn.min.js"></script>
    <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@{{ APLINE_VERSION }}/dist/cdn.min.js"></script>
    
    <!-- 2. Include the mock server script -->
    <script src="https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@{{ APLINE_AJAX_VERSION }}/dist/server.js"></script>
    
    <!-- 3. Define mocked routes -->
    <script>
    route('POST', '/update-quantity', (request) => {
      return `<output id="current_quantity">${Number(request.quantity)}</output>`
    })
    </script>
    
    <!-- 4. Use Alpine AJAX as normal -->
    <output id="current_quantity">0</output>
    <form x-target="current_quantity" method="POST" action="/update-quantity">
      <input type="number" name="quantity">
      <button>Update</button>
    </form>