---
title: 'Кнопка Load More на AJAX в OctoberCMS'
url: 'https://graker.ru/news/2018/02/01/load-more-button-ajax-octobercms'
language: ru
type: post
author: 'Роман Грачев'
published: '2018-02-01T10:31:00+03:00'
updated: '2018-02-01T10:41:47+03:00'
categories:
  - OctoberCMS
  - Программирование
---

# Кнопка Load More на AJAX в OctoberCMS

Работу с AJAX в OctoberCMS я уже раньше немного затрагивал, но [для бэк-энда](https://graker.ru/news/2017/07/04/octobercms-ajax-popup-widget). А теперь можно затронуть и фронт. В этой заметке мы сделаем кнопочку Load More, чтобы подгружала без перезагрузки страницы новые посты блога (из плагина RainLab.Blog).

На первый взгляд может показаться, что для этого нужно влезть в компонент Posts этого плагина, но на самом деле — вовсе не нужно. Дело в том, что раньше из документации можно было подумать, что обработчики AJAX-событий нужно описывать только в классе контроллера (если в бэк-энде), или компонента (если во фронте). И поэтому не очень было понятно, как быть, когда ты хочешь получить красивый ajax-пейджер для блога. То ли лезть в код чужого плагина, что влечет проблемы с обновлениями. То ли писать свой собственный компонент, из которого грузить компонент Posts программно. Что ведет к сомнениям в том, надо ли вообще такой негибкой CMS пользоваться.

Но то ли документацию дополнили, то ли в глазах у меня прояснилось (а может и то, и другое) — в общем, выяснилось, что в хендлеры ajax-событий годятся не только методы контроллеров/компонентов, но и функции, размещенные в секции PHP страниц и лейаутов ([но не паршлов](http://octobercms.com/docs/cms/partials#life-cycle-limitations)).

То есть мы можем сделать в htm-файле страницы вот так:

```
url = "/blog/posts"

[blogPosts allPosts]
pageNumber = 1
postsPerPage = 12
noPostsMessage = "No posts found"
sortOrder = "published_at desc"
==
function onLoadMore()
{
    // загрузить еще постов
}
==
<div class="blog-list">
  {% partial 'blogPosts' %}
</div>
```

И функцию `onLoadMore()` можно будет использовать как обработчик ajax-события. Тогда мы сможем сделать кнопку, не трогая плагин и не умножая сущности.

Допустим у нас есть такая разметка:

```
<div>
    {% component 'allPosts' %}
</div>
<div id="load-more-button">
    <a data-request="onLoadMore" data-request-data="page: 1" href="#">Load More</a>
</div>
```

Компонент `allPosts` — это лента постов `Posts` из плагина `RainLab.Blog`. Кнопку загрузки мы выводим вне компонента с постами, а сам компонет выглядит как-нибудь так:

```
<div id="all-posts-content" class="row">
    {% for post in posts %}
    <!-- Здесь выводятся посты, как обычно -->
    {% endfor %}
</div>
```

По клику на кнопку Load More на сервере будет вызвана функция `onLoadMore`, которую мы добавили в php-секцию нашей страницы:

```
function onLoadMore() {
    // получаем номер страницы
    $pageNumber = Input::get('page') + 1;
    // обращаемся к компоненту Posts с alias allPosts: 
    // выставляем номер страницы и готовим данные
    $this->components['allPosts']->setProperty('pageNumber', $pageNumber);
    $this->components['allPosts']->onRun();
    if ($pageNumber < $this->components['allPosts']->posts->lastPage()) {
        // для простоты мы генерируем html, но в принципе можно сделать и отдельный паршл для кнопки
        $more_link = '<a data-request="onLoadMore" data-request-data="page: ' . $pageNumber . '" href="#">Load More</a>';
    } else {
        // если мы достигли последней страницы, кнопка больше не нужна
        $more_link = '';
    }
    return [
        // если перед селектором стоит @, новое содержимое будет добавляться в конец, а не заменять старое
        '@#all-posts-content' => $this->components['allPosts']->renderPartial('@default.htm'),
        '#load-more-button' => $more_link,
    ];
}
```

Обратите внимание, что на сервер будут переданы данные из `data-request-data`, то есть номер страницы. Он используется, чтобы можно было нажимать на кнопку многократно и подгружать следующие блоки данных. Для этого мы в конце и код самой кнопки перегружаем — чтобы новый номер страницы вывести.

Вот и всё. Остальное за нас делает OctoberCMS.
