- Что потребуется для примера
- Подготавливаем конфигурации отдельных блоков
- Создаем общую конфигурацию редактора
- Создаем TV для редактора блоков
- Проверяем структуру сохраненных данных
- Создаем чанк блока About
- Создаем чанк отзывов с вложенным списком
- Как учитывать пути изображений
- Выводим блоки на странице
- Проверяем редактор блоков
- Следующий шаг
В основном уроке MIGX мы разобрали обычные записи, вложенные списки и изображения. Теперь рассмотрим другой сценарий MIGX в MIGX: список секций, у которых могут быть разные формы редактирования.
Например, редактор добавляет текстовый блок, затем отзывы, меняет их порядок и заполняет содержание. Для каждой секции используется своя конфигурация, а все записи хранятся в одном общем TV.
В этой статье используем Multiple Formtabs и вывод через Fenom. Это дополнительный разбор возможностей компонента, а не обязательная переделка уже работающего Creative.
Примеры оформления ниже сохранены из прежней практики. Для Creative и другой HTML-основы нужно использовать их собственную разметку и библиотеки. Первый экран и About из предыдущего урока автоматически переносить в этот редактор не требуется.
Что потребуется для примера
Нужны установленный MIGX, совместимая версия pdoTools и настроенная обработка Fenom. Ace пригодится для редактирования кода в админке.
В этом варианте код цикла размещается непосредственно в шаблоне, а оформление секций — в чанках, обрабатываемых pdoTools:
pdotools_fenom_parser— обработка Fenom непосредственно в шаблоне страницы.pdotools_fenom_default— обработка Fenom в чанках pdoTools.
Для приведенных примеров не требуется включать расширенный доступ через pdotools_fenom_php и pdotools_fenom_modx. Подробная настройка разобрана в уроке Fenom.

Скриншот показывает прежний интерфейс настроек. Ориентируйтесь на назначение параметров в тексте, а не включайте все доступные настройки по образцу изображения.
Перед этим упражнением нужно понимать конфигурации MIGX, TV, чанки и вложенные записи. Если эти понятия пока вызывают вопросы, сначала пройдите основной урок MIGX.
Первая версия статьи подготовлена по стороннему видео «Неоднородное содержимое или конфигуратор лендингов». Видео не мое; сохраняю его как дополнительный материал. Названия полей и оформление могут отличаться от примеров ниже.
Подготавливаем конфигурации отдельных блоков
Для редактора достаточно двух разных типов секций. Необязательно заранее создавать три блока или фиксированное количество конфигураций.
В примере используем:
about— текстовая секция с кнопкой и изображением.testimonials— секция отзывов с вложенным списком.testimonials_config— конфигурация одного вложенного отзыва.
Создайте их через менеджер конфигураций MIGX по порядку из предыдущего урока. Если такие конфигурации уже существуют, сначала сравните имена и поля, а не создавайте дубликаты.
| Конфигурация | Поля |
|---|---|
about |
title, subtitle, text, link, name_buttons, image. |
testimonials |
title, subtitle, slides. |
testimonials_config |
text_reviews, name, professiya, foto. |
Для коротких строк используйте текстовый ввод, для описаний — текстовую область, для image и foto — тип image.
У поля slides выберите тип migx и в Configs укажите testimonials_config. Так форма секции отзывов будет содержать собственный список записей.
В приведенных чанках описания выводятся как обычный текст. Если выбираете richtext и хотите сохранять HTML, потребуется отдельно согласовать способ его вывода.
Для изображений в этом примере используем сохраненные пути относительно корня проекта, например assets/img/example.jpg, без начального слеша. Если у вас другой источник или формат значений, подготовку адресов нужно изменить.

На архивном снимке конфигураций может быть больше. Для текущего упражнения нужны две внешние формы и конфигурация вложенного отзыва.
Создаем общую конфигурацию редактора
В менеджере MIGX добавьте еще одну конфигурацию:
- Name:
config. - Замена надписи «Добавить элемент»:
Добавить блок. - Window Title:
Редактор блоков.
Если имя config уже занято в вашем проекте, выберите другое и замените его во всех связанных местах инструкции.

Перейдите на Formtabs. В Multiple Formtabs выберите основные конфигурации about и testimonials. В Multiple Formtabs Label укажите «Выберите блок».

Добавляем только конфигурации целых секций.
testimonials_configздесь не нужен: его использует вложенное полеslides. Не добавляйте одну и ту же конфигурацию одновременно как секцию и как ее внутреннюю запись без отдельной задачи.
При использовании Multiple Forms у записи появляется поле MIGX_formname. Оно определяет выбранный тип формы. В этом примере ожидаем значения about и testimonials; ниже проверим их в сохраненных данных.
Если в настройках конфигураций используются Multiple Formtabs Optionsvalue, задайте соответствующие значения about и testimonials. Подпись в списке выбора и техническое значение типа — не обязательно одно и то же.
На вкладке Columns добавьте колонку:
- Header:
Тип блока. - Field:
MIGX_formname.

Сохраните колонку и всю конфигурацию.

Создаем TV для редактора блоков
При необходимости создайте категорию page builder, чтобы сгруппировать элементы. На работу вывода название категории не влияет.

Создайте TV:
- Имя:
config. - Подпись:
Блоки страницы. - Категория:
page builderили ваша существующая категория.

В параметрах ввода выберите тип migx, а в конфигурациях укажите config. Назначьте TV нужному шаблону и сохраните.

Если вложенные поля используют изображения, проверьте источники файлов. Вложенность сама по себе не гарантирует, что каждое поле сохранит путь в ожидаемом формате.
Заново откройте ресурс с назначенным шаблоном. В дополнительных полях должен появиться список блоков с выбором формы.

Добавьте одну запись About, заполните ее поля и сохраните. Затем добавьте секцию отзывов, заполните ее заголовки и несколько вложенных отзывов.
Сохраните вложенные записи, внешние записи блоков и затем сам ресурс.

В этом учебном примере добавляем по одной секции каждого типа. Их разметка содержит фиксированные ID about и testimonials. Для нескольких копий одного типа потребуется отдельно подготовить уникальные ID и проверить инициализацию JavaScript.
Проверяем структуру сохраненных данных
На локальной копии или закрытой тестовой странице временно добавьте в шаблон:
{set $blocks = $_modx->resource.config | fromJSON}
{$blocks | print}
Откройте страницу. Должен появиться массив заполненных блоков.

Найдите поле MIGX_formname у каждой внешней записи. Не путайте его с опечаткой MIGX_forname: для нашего вывода используется именно MIGX_formname.
Остальные ключи — имена полей конфигурации. Вложенный список slides содержит JSON, который нужно отдельно преобразовать перед циклом по отзывам.
Если значения типа отличаются от about и testimonials, сначала согласуйте их с настройками форм и кодом вывода. Не ориентируйтесь только на видимую подпись в выпадающем списке.
Отладочный вывод может раскрыть заполненные данные страницы. Не оставляйте его на общедоступном сайте. После проверки удалите вызов print и замените диагностический блок рабочим выводом из последнего раздела.
Создаем чанк блока About
Создайте обычный чанк с именем about. Он получит текущую запись через переменную data:
<section id="about" class="about">
<div class="container" data-aos="fade-up">
<div class="row gx-0">
<div class="col-lg-6 d-flex flex-column justify-content-center"
data-aos="fade-up" data-aos-delay="200">
<div class="content">
{if $data.subtitle}
<h3>{$data.subtitle | escape}</h3>
{/if}
<h2>{$data.title | escape}</h2>
<p>{$data.text | escape | nl2br}</p>
{if $data.link && $data.name_buttons}
<div class="text-center text-lg-start">
<a href="{$data.link | escape}"
class="btn-read-more d-inline-flex align-items-center justify-content-center align-self-center">
<span>{$data.name_buttons | escape}</span>
<i class="bi bi-arrow-right" aria-hidden="true"></i>
</a>
</div>
{/if}
</div>
</div>
<div class="col-lg-6 d-flex align-items-center"
data-aos="zoom-out" data-aos-delay="200">
{if $data.image}
<img src="{$_modx->config.base_url | escape}{$data.image | escape}"
class="img-fluid" alt="{$data.title | escape}">
{/if}
</div>
</div>
</div>
</section>
Сохраните чанк. Обращение вида {$data.title} получает поле текущей записи блока, а не стандартное поле ресурса.
Текстовые значения экранируем. Ссылки должны содержать допустимые адреса: экранирование HTML не проверяет протокол и назначение URL.
Условие вокруг подзаголовка убирает весь тег, если поле пустое. Условие кнопки проверяет и адрес, и подпись.
Создаем чанк отзывов с вложенным списком
Создайте чанк с именем testimonials. В нем сначала выводим поля секции, затем преобразуем slides и перебираем вложенные записи:
{set $items = $data.slides | fromJSON}
<section id="testimonials" class="testimonials">
<div class="container" data-aos="fade-up">
<header class="section-header">
<h2>{$data.title | escape}</h2>
{if $data.subtitle}
<p>{$data.subtitle | escape}</p>
{/if}
</header>
{if $items}
<div class="testimonials-slider swiper"
data-aos="fade-up" data-aos-delay="200">
<div class="swiper-wrapper">
{foreach $items as $item}
<div class="swiper-slide">
<div class="testimonial-item">
<div class="stars" aria-hidden="true">
<i class="bi bi-star-fill"></i>
<i class="bi bi-star-fill"></i>
<i class="bi bi-star-fill"></i>
<i class="bi bi-star-fill"></i>
<i class="bi bi-star-fill"></i>
</div>
<p>{$item.text_reviews | escape | nl2br}</p>
<div class="profile mt-auto">
{if $item.foto}
<img src="{$_modx->config.base_url | escape}{$item.foto | escape}"
class="testimonial-img"
alt="{$item.name | escape}">
{/if}
<h3>{$item.name | escape}</h3>
<h4>{$item.professiya | escape}</h4>
</div>
</div>
</div>
{/foreach}
</div>
<div class="swiper-pagination"></div>
</div>
{/if}
</div>
</section>
Сохраните чанк.
Здесь data — внешняя запись секции, а item — один вложенный отзыв. Список проверяем после fromJSON, а не только по наличию текста в поле: строка [] может содержать пустой массив.
Пять звезд сохранены как часть демонстрационного оформления. Это статические иконки, а не рассчитанный рейтинг.
Разметка отзывов зависит от CSS и JavaScript исходной верстки, включая Swiper, иконки и AOS. MIGX не подключает и не запускает их автоматически. Если вам нужен самостоятельный пример карусели, используйте урок слайдеров.
Как учитывать пути изображений
В чанках выше к значениям image и foto добавляется base_url. Это рассчитано на сохраненные пути относительно корня проекта, например assets/img/example.jpg.
Если поле уже содержит полный URL или путь с начальным слешем, повторно добавлять базовый адрес нельзя. Если источник сохраняет только имя файла, сначала нужно учесть его базовую папку.
Это особенность прямого вывода сохраненного JSON, а не утверждение, что MIGX вообще не умеет работать с источниками. В getImageList предусмотрена обработка полей по конфигурации TV, а прямой цикл Fenom не повторяет ее автоматически.

Если адрес неверный, сначала посмотрите фактическое сохраненное значение и получившийся src. Подробности разобраны в разделе об изображениях основного урока MIGX.
Архивный пример: блок с Bootstrap-каруселью
В прежней версии статьи использовался еще один тип блока со списком bs_carusel. Сохраняю его как дополнительный пример вложенного массива, а не обязательную часть текущего упражнения.

Фрагмент ниже относится к прежнему варианту Bootstrap с атрибутами data-ride и data-slide. Не вставляйте его в Creative на Bootstrap 5 без адаптации разметки и проверки JavaScript.
В этом отдельном архивном примере поле slide содержит имя файла, а изображения находятся в каталоге img/ от корня проекта. Если ваши значения устроены иначе, измените подготовку пути.
{set $items = $data.bs_carusel | fromJSON}
{if $items}
<div id="carouselExampleCaptions" class="carousel slide" data-ride="carousel">
<div class="carousel-inner">
{foreach $items as $idx => $item}
<div class="carousel-item{if $idx == 0} active{/if}">
<img src="{$_modx->config.base_url | escape}img/{$item.slide | escape}"
class="d-block w-100"
alt="{$item.zagolovok | escape}">
<div class="carousel-caption d-none d-md-block">
<h5>{$item.zagolovok | escape}</h5>
<p>{$item.opisanie | escape}</p>
</div>
</div>
{/foreach}
</div>
<a class="carousel-control-prev" href="#carouselExampleCaptions"
role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Предыдущий</span>
</a>
<a class="carousel-control-next" href="#carouselExampleCaptions"
role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Следующий</span>
</a>
</div>
{/if}
Для включения такого блока в общий редактор потребуется его собственная конфигурация и отдельное разрешенное соответствие типа и чанка в коде вывода. Два основных типа ниже не вызывают карусель автоматически.
Выводим блоки на странице
Удалите временный диагностический вывод и поставьте на его место:
{set $blocks = $_modx->resource.config | fromJSON}
{if $blocks}
{foreach $blocks as $block}
{if $block.MIGX_formname == 'about'}
{'about' | chunk : [
'data' => $block
]}
{elseif $block.MIGX_formname == 'testimonials'}
{'testimonials' | chunk : [
'data' => $block
]}
{/if}
{/foreach}
{/if}
Каждая запись передается в свой чанк через параметр data. Блоки выводятся в порядке списка MIGX.
Вместо вызова произвольного чанка по любому значению из данных здесь явно разрешены два типа: about и testimonials. Если добавляете новую форму, дополните соответствие в коде вывода.
Незнакомый тип в этом примере не выводится. Если секция пропала, сначала сравните фактическое значение MIGX_formname с условиями, а затем проверьте имя и содержание чанка.
Разместите общий вывод вместо прежних статических секций или их отдельных вызовов. Не оставляйте оба способа одновременно: иначе блоки продублируются.
Multiple Forms не требует именно Fenom. MIGX также умеет выбирать обычный чанк по полю через
&tpl=`@FIELD:MIGX_formname`. Но такие чанки должны использовать подходящий для этого способа синтаксис. Нельзя просто заменить наш Fenom-цикл этим параметром и ожидать, что все примеры станут взаимозаменяемыми.
Проверяем редактор блоков
- Измените заголовок одного блока и сохраните запись и ресурс.
- Поменяйте порядок двух внешних записей и проверьте порядок на сайте.
- Добавьте отзыв внутри секции и проверьте его появление.
- Очистите необязательный подзаголовок: его пустой тег не должен оставаться.
- Проверьте адреса изображений и загрузку библиотек исходного оформления.
- Убедитесь, что диагностический print удален, а секции не дублируются.
Не переключайте уже заполненную запись на другую форму без сохранения копии данных. Наборы полей могут отличаться, и смена формы не является автоматическим преобразованием одного типа блока в другой.
Если форма не открывается, проверьте выбранные конфигурации и ошибки запроса MIGX. Если форма работает, но содержимое не выводится, проверьте обработку Fenom, значения MIGX_formname и чанки.
Следующий шаг
Мы рассмотрели дополнительную возможность MIGX: общий список секций с разными формами и вложенными записями. Это пример организации содержания, а не готовая замена всем инструментам редактирования страниц.
Дальше возвращаемся к учебному Creative и подключаем портфолио через Gallery. Сравним этот способ с уже подготовленным вариантом на MIGX.
Основные настройки и справочник находятся в основном уроке MIGX.











