В этой инструкции, я бы хотел затронуть одну "киллер фичу" OctoberCMS и его AJAX фреймворка - обновление фрагментов. Полностью "обуздав" данный функционал вы действительно можете делать очень интересные вещи на своих проектах.
В разных кейсах, бывают ситуации, когда вам необходимо по нажатию кнопки или просто по срабатыванию JS события обновить кусок кода на странице с новой информацией, которая берется из базы.
Представим такую ситуацию: на сайте есть блок где выводится какая-нибудь вдохновляющая статья, и мы даем пользователю возможность загрузить на ее месте другую случайную статью по нажатию кнопки.
Помните, чтобы работал AJAX фреймворк в вашем шаблоне или странице он должен быть подключен через {% framework extras %}
.
Давайте создадим сначала фрагмент, который мы будем использовать на сайте.
Заходим в Панель управления -> CMS -> Фрагменты
создаем любой фрагмент с любым названием.
Я создал фрагмент card.htm - Карточка.
Добавим в тело фрагмента следующий код:
<h2>{{ item.name }}</h2>
<article>{{ item.description|raw }}</article>
Создаем страницу, в которую добавляем вызов нашего фрагмента {% partial 'card' %}
. Я использую Demo шаблон, который идет предустановленным при установке OctoberCMS.
Обратите внимание, что родительский блок фрагмента, имеет id="article"
. Нам необходимо обозначить родительский блок id атрибутом, иначе AJAX обновление работать не будет. Таким образом мы обозначаем обертку нашего элемента, внутри которого будет происходить обновление фрагмента.
Теперь давайте сделаем так, чтобы на страницу передавался контент во фрагмент из модели Item нашего плагина.
Item - это модель данных, которая содержит в себе заголовок и текст. Если вы не знаете как создать свою модель данных, можете прочитать это в моей инструкции тут: Создание плагина через Artisan. Инструкция для новичков. Часть 1.
На нашей странице нажмем на кнопку "Код" и введем туда функцию, которая будет забирать одну запись из нашей модели и просто выдавать ее на страницу.
Добавим следующий код;
function onStart()
{
$this['item'] = \OctoClub\Tutorial\Models\Item::first();
}
Должно получится так:
Откроем страницу и увидим что у нас выводится запись с заголовком и текстом.
Половина пути преодолена! Теперь нам нужно сделать кнопку, по нажатию которой будет происходить вся магия.
Добавим ее над статьей, чтобы не искать ее внизу страницы.
<div class="jumbotron title-js">
<div class="container">
<div class="row">
<div class="col-8">
<h1>Обновление фрагмента.</h1>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-xs-12">
<button class="btn btn-primary">Мне повезет!</button>
</div>
</div>
<div class="row">
<div class="col-xs-12" id="article">
{% partial 'card' %}
</div>
</div>
</div>
Теперь у нас есть кнопка.
Добавим на нее специальный атрибут, который будет вызывать функцию для обновления фрагмента.
<button data-request="onRandom" class="btn btn-primary">Мне повезет!</button>
Помните, что названия AJAX хандлеров должны быть написаны по примеру: onSomething
.
Отлично, вы добавили обработчик. Давайте нажмем и посмотрим что произойдет.
AJAX успешно обрабатывает нажатия на кнопку, и теперь он просто пытается найти наш хандлер, который мы еще не создавали. Данный тест я провожу всегда, чтобы убедится что AJAX обрабатывает эту кнопку и все идет как надо. Если у вас не появляется эта ошибка, проверьте подключен ли у вас {% framework extras %}
или {% framework %}
в шаблоне вашего сайта или страницы.
Давайте перейдем в раздел "Код" нашей страницы. И добавим туда хандлер.
Под функцией onStart()
добавляем:
function onRandom()
{
}
И пишем сюда небольшую логику. которая будет обновлять наш фрагмент, и передавать в него данные о новой записи. Обратите внимание, что мы будем передавать данные во фрагмент, а не на страницу, поэтому новые данные могут быть использованы только внутри фрагмента.
function onRandom()
{
return [
'#article' => $this->renderPartial('card', ['item' => \OctoClub\Tutorial\Models\Item::inRandomOrder()->first()])
];
}
Все что мы делаем это:
Возвращаем в блок #article вызов рендера фрагмента 'card' с переменной item в которой лежит Item::inRandomOrder()->first()
- случайная одна запись из модели.
Теперь перейдем на страницу и нажмем на кнопку!
Контент обновляется, вы великолепны!
Вы можете вместо секции "Код" страницы, разместить этот хандлер в свой компонент, а фрагмент создавать не в CMS а положить рядом с default.htm вашего компонента. Единственное что будет отличаться в хандлере это вызов фрагмента.
Я делаю обычно так:
$this->renderPartial($this.'::card', ['item' => \OctoClub\Tutorial\Models\Item::inRandomOrder()->first()])
Если вы хотите вместо замены фрагмента вставить новый контент после существующего, это очень просто, достаточно добавить @
перед #article в хандлере чтобы получилось: '@#article' =>
Или чтобы добавить ПЕРЕД существующим фрагментом, надо добавить символ ^
получится: '^#article' =>