AJAX-пагинация (кнопка загрузить ещё) в October CMS — deadblog.ru

AJAX-пагинация (кнопка загрузить ещё) в October CMS

Написал я компонент, и оказалось так, что вывожу сотню-другую элементов в рамках этого компонента. Естественно, что для этого добра нужна пагинация.

Не захотел делать пагинацию в виде циферок, по клику на которые меняются страницы с элементами. Решил, что сделаю кнопку «Загрузить ещё» при помощи AJAX.

Не буду подробно описывать про компонент и т.д., опишу самые главные вещи, чтобы копировал-вставил и заработало.

В первую очередь засунем всю списочную часть из default.htm в отдельный partial и добавим div#list и div#load-more-button:

<div id="list">
    {% partial '@_list' %}
</div>

<div id="load-more-button" class="loadmore">
    <a data-request="onLoadMore" data-request-data="page: 1" href="#">Загрузить ещё</a>
</div>

div#list нужен для вывода списка, а div#load-more-button для замены кнопки на ничего, в случае, если кончились элементы.

{% set items = __SELF__.items %}

{% for item in items %}
    {# ... #}
{% else %}
    <li class="no-data">No items found.</li>
{% endfor %}
<a data-request="onLoadMore" data-request-data="page: {{ pageNumber }}" href="#">Загрузить ещё</a>

Добавляем в модель функцию scopeListFrontEnd, которая запрашивает содержимое из бд, попутно разбивая его на страницы:

class MyModel extends Model 
{
    public function scopeListFrontEnd($query, $options = []) 
    {
        extract(array_merge([
            'page'    => 1,
            'perPage' => 10,
        ], $options));

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

Как параметры, мы передаём текущую страницу и количество элементов на странице.

Теперь расширим класс компонента:

class ComponentClass extends ComponentBase
{
    public $items;

    public function defineProperties()
    {
        'pageNumber' => [
            'title'       => 'Page Number',
            'description' => 'Description',
            'type'        => 'string',
            'default'     => '{{ :page }}',
        ],
    }

    public function onRun()
    {
        $this->items = $this->loadItems():

        // если в url страница больше, чем всего страниц, то редиректим на последнюю
        if ($pageNumberParam = $this->paramName('pageNumber')) {
            $currentPage = $this->property('pageNumber');
            if ($currentPage > ($lastPage = $this->items->lastPage()) && $currentPage > 1) {
                return Redirect::to($this->currentPageUrl([$pageNumberParam => $lastPage]));
            }
        }
    }

    public function loadItems()
    {
        $items = MyModel::listFrontEnd([
            'page'    => $this->property('pageNumber'),
            'perPage' => 10,
        ]);

        return $items;
    }

    /*
     * Данная функция вызывается по клику на кнопку "Загрузить ещё"
     */
    public function onLoadMore()
    {
        // получаем номер страницы
        $pageNumber = Input::get('page') + 1;

        // выставляем номер страницы и готовим данные
        $this->setProperty('pageNumber', $pageNumber);
        $this->onRun();

        if ($pageNumber < $this->items->lastPage()) {
            $more_link = $this->renderPartial('@_morelink.htm', ['pageNumber' => $pageNumber]);
        } else {
            $more_link = ''; // если мы достигли последней страницы, кнопка больше не нужна
        }

        return [
            // если перед селектором стоит @, новое содержимое будет добавляться
            // в конец, а не заменять старое
            '@#list'            => $this->renderPartial('@_list.htm'),
            '#load-more-button' => $more_link,
        ];
    }

}

Не забудь для страницы добавить в url "/page/:page?/", и готово 🙂


13 комментариев на «“AJAX-пагинация (кнопка загрузить ещё) в October CMS”»

  1. Здравствуйте!
    Пытаюсь воспользоваться решением «копировал-вставил и заработало» и никак:

    Call to a member function lastPage() on null

    В этой строке:

    if ($currentPage > ($lastPage = $this->items->lastPage()) && $currentPage > 1) {

    Почему так?

    P.S. В этой строке исправлено questions на items

      • public function onRun()
        {
        $items = $this->loadItems():

        // если в url страница больше, чем всего страниц, то редиректим на последнюю
        if ($pageNumberParam = $this->paramName('pageNumber')) {
        $currentPage = $this->property('pageNumber');
        if ($currentPage > ($lastPage = $this->items->lastPage()) && $currentPage > 1) {
        return Redirect::to($this->currentPageUrl([$pageNumberParam => $lastPage]));
        }
        }
        }

        здесь просто глобального $items надо инициализировать

  2. $this->renderPartial(‘@_morelink.htm’, [‘pageNumber’ => $pageNumber]);
    здесь на партиали что я должен делать?

  3. Вопрос новичка. MyModel.php, ComponentClass.php где эти файлы находятся или мы создаем новый плагин с данными файлами? Как должна выглядеть иерархия файлов.

    • Пример в статье — как сделать пагинацию в своём плагине.
      ComponentClass.php — это класс компонента, он находится в /plugins/author/pluginName/components/
      MyModel.php — это класс модели, он находится в /plugins/author/pluginName/models/

    • Лажа — это твой комментарий. Вместо балабольства мог бы предметно написать чего не хватает или кинуть ссылку на более полный гайд.

  4. Здравствуйте, есть ли внедренное решение или место где скачать плагин. Здесь много опечаток. Но их поправил. И как не внедрял, не работает и много вопросов. откуда @_morelink.htm, почему через @, что внутри него писать? переделал на _list. При нажатии на кнопку, модуль подгружает посты той же страницы.На главной никак не получается настроить, чтобы он передавал номер страницы. Не может получить Input::get(‘page’) + 1; Было бы здорово приложить папку с плагином (со всеми файлами). и как выглядят внутри list.hm и morelink.htm (или хотя бы скрин) и куда прописывать этот путь: /page/:page?/ . Это же ajax — ссылка не должна меняться. (статья https://deadblog.ru/webdev/ajax-paginatsiya-knopka-zagruzit-eshhyo-v-octobercms/)

    • Что за опечатки? Скопировал пример из статьи, всё работает, никаких опечаток не нашёл.

      Что касается @_morelink.htm, то добавил в статью. Паршл _morelink.htm нужен, чтобы выводить кнопку с параметром page равным нужной страницы. Собственно у тебя не работало из-за того, что _morelink.htm не было 🙂

      /page/:page? — в админке перейди на CMS, выбери страницу для которой ты делаешь ajax-пагинацию и добавь для этой страницы в «Адрес» параметр /:page? (но можно и не добавлять, работать итак будет).

Добавить комментарий

Ваш адрес email не будет опубликован.