# Представления
← [К разделу «Как собирается сайт»](README.md)
Представление отвечает только за внешний вид готового набора данных. Оно не
выбирает документы, не меняет поля рубрики и не выполняет SQL.
Простая схема:
```text
рубрика и документы -> запрос или каталог -> представление -> HTML
```
Например, одна и та же подборка может быть показана карточками, компактным
списком или слайдером. Данные останутся прежними, изменится только
представление.
## Из чего состоит представление
В редакторе есть четыре части:
| Часть | Что делает |
| --- | --- |
| Элемент | Оформляет один документ или товар. Текущий объект доступен как `item`. |
| Обёртка | Собирает готовые элементы в список, сетку или слайдер. HTML элементов доступен как `content`. |
| Пустой результат | Показывается, если источник не вернул ни одной записи. |
| CSS | Подключается только на странице, где это представление реально отрисовано. |
Минимальный шаблон элемента:
```twig
{% if item.excerpt %}{{ item.excerpt }}
{% endif %}
```
Обёртка:
```twig
{{ content|raw }}
```
`content|raw` здесь обязателен: это уже готовый и проверенный HTML элементов.
Обычные значения вроде `item.title` Twig экранирует автоматически.
## Доступные данные
Вкладка **Данные** показывает значения, которые можно вставить в текущий
шаблон. Базовый документ предоставляет:
- `item.id`;
- `item.rubric_id`;
- `item.title`;
- `item.url`;
- `item.excerpt`;
- `item.description`;
- `item.published_at`;
- `item.views`;
- `item.image` и `item.thumb`;
- `item.fields`;
- `context.code`;
- `context.position`;
- `context.total`, `context.page` и `context.pages`.
Включённые модули дополняют этот список. Товарный модуль, например, добавляет
артикул, цену, изображения, варианты и действия. Не нужно запоминать имена:
нажмите нужную строку в палитре, и редактор вставит выражение Twig.
Для товарного списка также доступны:
- `item.stock` — логический признак наличия;
- `item.shipping_packages` — список грузовых мест;
- `actions.cart`, `actions.favorite`, `actions.compare` — данные публичных
действий.
Каждое грузовое место содержит `title`, `quantity`, `weight_kg`, `length_cm`,
`width_cm` и `height_cm`. Например:
```twig
{% for package in item.shipping_packages %}
{{ package.title }}:
{{ package.length_cm }} × {{ package.width_cm }} × {{ package.height_cm }} см
{% endfor %}
```
Данные действия описывают возможность и идентификатор операции. Сам HTML
кнопки остаётся частью представления, а обработчик корзины, избранного или
сравнения — частью соответствующего модуля.
## Черновик и публикация
Сохранение не меняет сайт. Рабочая последовательность:
1. Создайте представление.
2. Заполните элемент, обёртку и при необходимости CSS.
3. Проверьте Twig и откройте предпросмотр на реальном документе.
4. Сохраните черновик.
5. Опубликуйте проверенную версию.
6. Создайте назначение и только затем выберите режим **Новое представление**.
Публичный сайт всегда использует опубликованный снимок. Последующие правки
черновика не появятся на сайте до новой публикации.
## Режимы назначения
| Режим | Поведение |
| --- | --- |
| Текущий вывод (`legacy`) | Продолжает работать прежний шаблон. |
| Подготовка (`preview`) | Связь сохранена, но публичный вывод не переключён. |
| Новое представление (`native`) | Используется опубликованное представление. |
Новое назначение создаётся в безопасном режиме. Включить `native` для
неопубликованного представления нельзя.
Цель выбирается по названию. Редактор показывает реальные рубрики, запросы,
разделы каталога и установленные модули, поэтому искать и вводить ID вручную не
нужно. Если ранее выбранная сущность удалена, назначение помечается как
отсутствующее: его нужно удалить или заменить.
Назначения проверяются от частного к общему:
```text
конкретный каталог -> запрос -> рубрика -> модуль -> везде
```
Например, отдельное назначение каталога перекроет общее назначение товарного
модуля. Явный `legacy` на конкретном каталоге также перекрывает более широкое
`native`: это позволяет вернуть один раздел на прежний вывод.
## Подключённые места вывода
Общий renderer обслуживает следующие места:
- **Список материалов** — товарные ленты и каталожные листинги;
- **Штатные запросы** — обычные подборки документов по тегу
`[tag:request:...]`;
- **Список рубрики** — вывод `[mod_content_list:...]` для новостей, статей и
других типов контента;
- **Результаты поиска** — обычные документы, товары и смешанная выдача;
- **Похожие материалы** — обычные документы и товары;
- **Избранное** и **Просмотренные материалы** — списки покупателя.
Для назначения всему товарному контуру выберите нужное место, цель **Модулю**
и укажите код `products`. Для отдельного каталога можно выбрать цель
**Каталогу** и указать ID его раздела: такое назначение будет точнее
модульного.
Для обычного поиска можно назначить представление модулю `search`, для похожих
материалов — модулю `related`. Если все найденные документы относятся к одной
рубрике, её назначение будет точнее модульного. Назначение конкретному запросу
имеет ещё больший приоритет.
Чтобы оформить штатный запрос, выберите цель **Запросу** и его ID. При таком
назначении запрос продолжает отвечать за условия, сортировку, лимит и
пагинацию, а его старые шаблоны `main/item` заменяются представлением. Для
общего списка рубрики можно назначить представление цели **Рубрике**.
Широкие назначения модулю `requests` или `content` допустимы, но для первого
включения безопаснее выбрать конкретный запрос или рубрику.
Товарный адаптер запускается первым и добавляет цену, наличие, варианты и
действия. Если набор содержит не только товары, ядро собирает единый базовый
контракт документов. Половина списка никогда не оформляется одним способом, а
половина другим: либо всё представление готово, либо целиком используется
прежний renderer.
В поиске дополнительно доступны `item.search.relevance` и `context.query`. В
похожих материалах доступны `item.related.score`, `item.related.matches`,
`item.related.source`, а также данные профиля в `context.profile_id`,
`context.profile_code` и `context.profile_title`.
Штатный запрос передаёт `context.request_id` и готовую пагинацию в
`context.pagination_html`. Если она нужна внутри обёртки, выводите её как уже
готовый HTML:
```twig
{{ context.pagination_html|raw }}
```
В режиме `native` представление владеет обёрткой списка. Заголовок страницы,
форма поиска, число результатов, пагинация и кнопки очистки остаются у
соответствующего модуля. CSS представления подключается и при полной загрузке,
и при AJAX-обновлении списка.
Остальные места продолжают использовать свои действующие renderer-ы. Само
наличие представления ничего не переключает.
## Диагностика
Вкладка **Диагностика** запускает явную проверку перед публикацией:
- проверяет Twig элемента, обёртки и пустого результата;
- убеждается, что все назначения ведут к существующим сущностям;
- проверяет наличие опубликованной версии для режима `native`;
- собирает черновик на материале, выбранном во вкладке **Предпросмотр**.
Предупреждения ничего не переключают и не исправляют автоматически. Ошибку
нужно устранить до включения нового публичного вывода. Удалённые блоки,
запросы, навигации и модульные теги проверяются в **Публичный сайт →
Размещения**: там видны исходный шаблон и точный редактор компонента.
## Размещения и «Где используется»
Страница **Публичный сайт -> Размещения** показывает, где действующие шаблоны
подключают блоки, подборки, навигации и модульные теги. Это обзор существующего
сайта, а не отдельный конструктор:
- **До содержимого** — теги шаблона сайта до `[tag:maincontent]` и шаблон
рубрики, выполняемый перед документом.
- **Основное содержимое** — основной шаблон рубрики, блоки, навигации и общие
шаблоны запросов.
- **После содержимого** — теги после `[tag:maincontent]` и шаблон рубрики после
документа.
- **Метаданные** — разметка Open Graph рубрики.
- **Элемент списка** — шаблон элемента запроса или анонса.
Красная строка означает, что указанный блок, запрос или навигация больше не
существует. Выключенный блок помечается отдельно. Для модульного тега карта
показывает сам тег: его окончательную доступность контролирует установивший его
модуль.
Кнопка **Перестроить карту** повторно читает сохранённые шаблоны. Обычно она не
нужна: индекс автоматически сбрасывается после сохранения шаблона, рубрики,
блока, запроса или навигации.
Карта ничего не меняет в публичной части. Исправлять найденную связь нужно в
штатном редакторе, открываемом кнопкой в правой колонке.
## Защита от ошибок
Перед сохранением Twig проверяется. Дополнительно публичный renderer работает
с обязательным возвратом к прежнему выводу:
- назначение отсутствует — используется текущий шаблон;
- режим не `native` — используется текущий шаблон;
- опубликованная версия отсутствует — используется текущий шаблон;
- данные неполны или Twig выбросил ошибку — используется текущий шаблон, а
причина записывается в системный журнал.
Поэтому ошибочное представление не должно превращать страницу в ошибку 500 или
скрывать весь каталог.
## Пользовательская тема
Если тема переопределяет модульные шаблоны товарных списков, она должна
сохранить необязательную переменную `presentation`:
```twig
{% if presentation is not null %}
{{ presentation|raw }}
{% else %}
{# прежний вывод карточек #}
{% endif %}
```
Без этого назначения останутся безопасными, но тема продолжит показывать
прежнюю разметку. Штатные шаблоны AVE.cms этот контракт уже поддерживают.