Advanced AJAX actions

Estimated reading: 4 minutes

Here you will find a few examples of more advanced AJAX action calls.

Pagination

A pretty simple pagination example is this one. Even though it’s a templatetype htmx, it can be used as the basis of subsequent ajax calls. By simply using an {% include 'yourtemplatename.twig' %} this will render the first 6 posts on page, with both above and under them pagination links that will replace the entire ID’s content with the AJAX request’s result.

A macro is used to be sure that the pagination above and below the posts is exactly the same.

{#
  TemplateType: htmx
  Action: get-posts
#}
<div id="posts-archive">
    {%
    set args = {
        post_type: 'post',
        posts_per_page : 6,
        paged: request.get.page|default(1)
    }
    %}
    {% set posts = PostQuery( args ) %}
    {{ _self.pagination( posts ) }}
    <div class="uk-child-width-1-3@s uk-grid-match" uk-grid>
    {% for item in posts %}
    <div>
        <div class="uk-card uk-card-default uk-card-body">
            <h3>{{ item.title }}</h3>
            {{ item.preview().length(20) }} 
        </div>
    </div>
    {% endfor %}
    </div>
    {{ _self.pagination( posts ) }}
</div>

{% macro pagination( posts ) %}
<div class="uk-flex uk-flex-center">
    <ul class="uk-pagination uk-margin-top" uk-margin>
    {% for page in posts.pagination.pages %}
        <li>
            <a 
                href="#"
                hx-get="{{ ADMIN_AJAX_URL ~ '?' ~ { action: 'get-posts' , page : page.title }|build_query }}"
                hx-swap="outerHTML"
                hx-target="#posts-archive"
                class="{{ page.current ? 'uk-active' }}">
                {{ page.title }}
            </a>
        </li>
    {% endfor %}
    </ul>
</div>
{% endmacro %}

Banner rotator

A very simple banner rotator can be created using a htmx call. In case of a real banner or image, it could get images from an array of URLs, an ACF gallery field or whatever comes to mind. This example replaces itself every 30 seconds and increments the variable ‘current_banner’ that is used to render a new number.

Just like the previous template, this one can be added to a page using a {% include 'yourtemplatename.twig' %}.

{#
    TemplateType: htmx
    Action: banner-rotate
#}
<div 
    hx-get="{{ ADMIN_AJAX_URL ~ '?action=banner-rotate' }}"
    hx-swap="outerHTML"
    hx-trigger="load delay:30s">
    {# get the current banner number from the options table #}
    {% set current_banner = tb.get_option( 'htmx_current_banner' , 0 ) %}
    <div class="uk-text-center">
        <h2 class="uk-heading-small">This is banner #{{ current_banner }}</h2>
    </div>
    {# update the number in the options table, use modulo to keep it below 5 #}
    {% set current_banner = tb.update_option( 'htmx_current_banner' , (current_banner + 1) % 5 ) %}
</div>

Post search form

How about a template that shows paginated posts and adds an AJAX search feature?

It combines the pagination template above with a input field that triggers getting posts with a certain keyword. Note that the request variable needs to be forwarded to make sure it is scoped within the macros.

{#
    TemplateType: htmx
    Action: htmx-search
#}
{% if request.get.c is not defined %}
    <input type="text" name="q"
        hx-get="{{ ADMIN_AJAX_URL ~ "?" ~ { action: 'htmx-search' , c : 'get' }|build_query }}"
        hx-trigger="keyup changed delay:500ms"
        hx-target="#search-results"
        placeholder="Search..."
    >
    <div id="search-results">
        {{ _self.search_archive( request ) }}
    </div>
{# triggered when the input field changes #}
{% else %}
    {{ _self.search_archive( request ) }}
{% endif %}


{% macro search_archive( request ) %}
    {%
    set args = {
        post_type: 'post',
        s: request.get.q|default( null ),
        posts_per_page : 6,
        paged: request.get.page|default(1),
    }
    %}
    {% set posts = PostQuery( args ) %}
    {% if posts|length %}
        <div id="search-archive">
            <div class="uk-child-width-1-3@s uk-grid-match" uk-grid>
            {% for item in posts %}
                <div>
                    <div class="uk-card uk-card-default uk-card-body">
                        <h3>{{ item.title }}</h3>
                        {{ item.preview().length(20) }} 
                    </div>
                </div>
            {% endfor %}
            </div>
            {{ _self.pagination( posts , request ) }}
        </div>
    {% else %}
        <p>There are no results.</p>
    {% endif %}
{% endmacro %}

{% macro pagination( posts , request ) %}
    <div class="uk-flex uk-flex-center">
        <ul class="uk-pagination uk-margin-top" uk-margin>
        {% for page in posts.pagination.pages %}
            <li>
                <a 
                    href="#"
                    hx-get="{{ ADMIN_AJAX_URL ~ '?' ~ request.get|merge({ c: 'getpage', page : page.title })|build_query }}"
                    hx-swap="outerHTML"
                    hx-target="#search-archive"
                    class="{{ page.current ? 'uk-active' }}">
                    {{ page.title }}
                </a>
            </li>
        {% endfor %}
        </ul>
    </div>
{% endmacro %}
Share this Doc

Advanced AJAX actions

Or copy link

CONTENTS