You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将October CMS Ajax分页改为加载更多按钮?附教程代码

Convert October CMS Ajax Pagination to "Load More" Button

Alright, let's revamp your existing numeric Ajax pagination into a user-friendly "Load More" button. I'll walk you through each step with code adjustments tailored to your current setup:


Step 1: Update Frontend Templates (movie-filter-ajax.htm)

First, we'll swap out the pagination dropdown/numbers for the load-more button and adjust how we track pages and update content.

1.1 Replace Pagination Controls with Load More Button

Find the #partialPaginate div and replace its contents with this:

<div class="field" id="partialPaginate">
    {% if page < pages %}
        <button type="button" id="loadMoreBtn" class="ui button primary">Load More</button>
    {% endif %}
    <input type="hidden" id="currentPage" value="{{ page }}">
</div>

We use the hidden input to track the current page, and only show the button if there are more pages to load.

1.2 Add Hidden Page Input to the Form

Inside your form_ajax block, add a hidden input to pass the current page number to the backend, and adjust the Ajax callback logic:

{{ form_ajax('onFilterMovies', { 
    dataType: 'html',
    beforeSend: function() {
        $('#loadMoreBtn').addClass('loading').attr('disabled', true);
    },
    success: function(data) {
        let currentPage = parseInt($('#currentPage').val());
        currentPage++;
        $('#currentPage').val(currentPage);
        
        // Append new movies to the list instead of replacing it
        $('#movieListContainer').append(data);
        
        // Hide button if we've reached the last page
        if (currentPage >= {{ pages }}) {
            $('#loadMoreBtn').hide();
        } else {
            $('#loadMoreBtn').removeClass('loading').attr('disabled', false);
        }
    }
}) }}
<!-- Add this hidden input to track page number -->
<input type="hidden" name="Filter[page]" value="1">
<!-- Rest of your filter form controls (genres, year, sorting) -->
{{ form_close() }}

1.3 Adjust Movie List Container

Wrap your movies partial in a container that we can append new content to:

<div class="eleven wide column">
    <div id="movieListContainer">
        {% partial 'movies/movies' %}
    </div>
</div>

Make sure your movies/movies partial only outputs individual movie items (no wrapping container that would get replaced):

{% for movie in movies %}
    <div class="movie-item ui segment">
        <h3>{{ movie.name }}</h3>
        <p>Release Year: {{ movie.year }}</p>
        <!-- Add your other movie details here -->
    </div>
{% endfor %}

1.4 Add Click Handler for Load More Button

Add this script at the bottom of your page to trigger form submissions with the next page number, and reset pagination when filters change:

$('#loadMoreBtn').on('click', function() {
    let currentPage = parseInt($('#currentPage').val());
    $('input[name="Filter[page]"]').val(currentPage + 1);
    $(this).closest('form').submit();
});

// Reset page number when filter options are changed
$('.movies-filter select, .movies-filter input[type="checkbox"]').on('change', function() {
    $('#currentPage').val(1);
    $('input[name="Filter[page]"]').val(1);
    $('#loadMoreBtn').show().removeClass('loading').attr('disabled', false);
    $(this).closest('form').submit();
});

Step 2: Tweak Backend Logic

1.1 Ensure Page Parameter is Handled Correctly

Update your page's prepareVars method to default to page 1 if no page is provided:

function prepareVars() {
    $options = post('Filter', []);
    // Set default page to 1 if not present in POST data
    $options['page'] = isset($options['page']) ? (int)$options['page'] : 1;
    $this['movies'] = Movie::listFrontEnd($options);
    $this['genres'] = Genre::all();
    $this['sortOptions'] = Movie::$allowedSortingOptions;
    $this['pages'] = $this['movies']->lastPage();
    $this['page'] = $this['movies']->currentPage();
}

1.2 Verify listFrontEnd Scope

Your existing Movie.php scopeListFrontEnd method already handles pagination correctly, but double-check it returns a paginated collection even for invalid page numbers:

public function scopeListFrontEnd($query, $options = []){
    extract(array_merge([
        'page' => 1,
        'perPage' => 10,
        'sort' => 'created_at desc',
        'genres' => null,
        'year' => ''
    ], $options));

    // ... existing sorting/filtering logic ...

    // Reset to page 1 if requested page is out of bounds
    $lastPage = $query->paginate($perPage, $page)->lastPage();
    if($lastPage < $page){
        $page = 1;
    }

    if($year){
        $query->where('year', '=', $year);
    }

    return $query->paginate($perPage, $page);
}

Key Notes

  • Prevent Duplicate Clicks: The beforeSend callback disables the button and adds a loading state until the request completes.
  • Reset on Filter Changes: When users adjust genres, year, or sorting, we reset the page number to 1 and re-show the load more button.
  • Hide Button When Done: Once the user reaches the last page, the button is hidden to avoid unnecessary requests.

内容的提问来源于stack exchange,提问作者MaxxQ90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 20:37:48