====== Композиция шаблонов: включение(include) и обворачивание(wrap) шаблонов ====== ===== Компиляция WACT шаблонов ===== WACT содержит различные средства, которые позволяют собирать конечные шаблоны из набора других шаблонов: * **Включение (include)** - включение одного шаблона в другой. * **Обворачивание (wrap)** - обворачивание одного шаблона другим. **Wact компилирует шаблоны только целиком!** То есть сначала обрабатываются все include и wrap теги, и только затем создается откомпилированный шаблон. Именно поэтому разбиение шаблона на составляюще в WACT практически ничего не стоит (лишь увеличивается незначительно время компиляции). Это дает нам возможность выносить в отдельные шаблоны все, что повторяется в нескольких файлах. Цель данной страницы - показать способы "снижения дублирования" в WACT-шаблонах, то есть как максимально эффективно использовать все возможности WACT по композиции шаблонов. Сразу же обратим ваше внимание, что в WACT существует правило **сбалансированности** шаблонов, то есть каждый шаблон должен иметь закрывающий тег для каждого открывающего. Это наносит свой отпечаток на то, как шаблоны разбиваются на составляющие. Но справедливости ради отметим, что этот факт обычно никак не мешает в работе с шаблонизатором, даже напротив. ===== Включение (include). Использование тега ===== Включение (include) одного шаблона в другой. Include в WACT осуществляется посредством тега . По-умолчанию, включаемый файл компилируется как обычный шаблон. Если вы используете WACT совместно с пакетом WEB_APP, и в атрибуте file используется абсолютное значение (начинается с **/** или с **c:/**), тогда WACT подключает шаблон по абсолютному пути. В противном случае - пытается найти шаблон через механизм подключения шаблонов. Компиляцию включаемого шаблона можно отключить, если использовать атрибут literal, например: . Из-за правила сбалансированности, вы не можете просто так применить любимый многими php-программистами прием - разбить шаблон на footer.html и header.html, то есть: **my_page.html** [...meta...] [...content...] Разбить на 2 шаблона: **header.html** [...meta...] **footer.html** **Вот так сделать в WACT не получится!!** **my_page.html**: [...content...] Для таких целей есть операция обворачивания (wrap), которая позволяет без проблем сохранить целостность базового шаблона и вынести контентную часть в отдельный шаблон. ===== Обворачивание (wrap) ===== ==== Введение в обворачивание шаблонов ==== Обворачивание (wrap) - это вставка шаблона в определенное место другого шаблона. С обворачиванием шаблонов связаны следующие термины: * Текущий шаблон - который содержит команды по обворачиванию (в нем содержатся теги ) * Базовый шаблон - в который осуществляется вставка текущего шаблона. * Контейнер вставки (placeholder) - находится в базовом шаблоне и помечает места вставки. Обворачивание производится при помощи тега . Контейнер обычно помечается тегом . Вот как будет выглядеть результат нашего предыдущего примера: **page.html** - базовый шаблон [...meta...] **my_page.html** - текущий шаблон [...content...] ==== Использование тега . Множественныое обворачивание ==== Разберем подробнее, как работает тег . требует закрывающего тега. Обворачиваемой считается та часть текущего шаблона, что обрамлена в рамки тега . Если тег не содержит атрибута file, тогда обворачивание производится в шаблон, который был указан родительским тегом . Таким образом мы можем как бы указать сначала целевой файл, а затем только указать какие части и куда обвернуть. Поясним это все на примере: Допустим есть базовый шаблон страницы page.html: Также шаблон дополнительного дизайна layout.html с двумя местами для вставки (как бы второй базовый шаблон):
И теперь текущий шаблон display.html: My Header My Complex content На выходе получим:
My Complex content
Необходимо пояснить, как именно компилируется шаблон в данном случае. Сначала обрабатывается первый и мы получаем на 1-м шаге компиляции следующий шаблон: My Header My Complex content Затем обрабатывается второй и условно получается:
My Header My Complex content
Обратите внимание, что дочерние теги (без атрибута file) могут найти контейнеры вставки только в отмеченной зоне (только внутри шаблона, указанного родительским ). В результате работы дочерних получается конечный результат. ==== Произвольные контейнеры вставки ==== Контейнер вставки не обязательно должен быть реализован при помощи тега . Для этих целей можно использовать вообще любой тег, например
. Необходимо будет лишь указать, что этот тег должен обрабатываться как тег с активным компонентом и дать ему идентификатор. Это можно сделать при помощи одного атрибута: **wact:id**, например:
Content will be placed here
можно использовать по-разному: * вставлять контент в конец содержимого контейнера. * заменять весь контент контейнера . Для этого теперь есть 2 атрибута: * **in**, например ... * **as**, например ... В первом случае содержимое между будет вставлено сразу же после содержимого контейнера вставки, во втором - полностью заменит контент внутри контейнера. ==== Контейнеры данных и множественное обворачивание ==== Самый сложный момент, который обычно представляет трудность для верстальщиков - это понимание, как будет выглядеть откомпилированный шаблон, а также понимание структуры контейнеров данных, которая будет существовать в шаблоне после компиляции. Разберем небольшой пример (предупреждаем, он может показаться весьма нетривильным для понимания). Путь у нас есть базовый шаблон page.html, в котором есть 2 контейнера вставки:

Предположим, что у нас есть такой текущий шаблон: {$title} {$content} На первый взгляд все нормально, мы должны получить конечный шаблон, где из контейнера данных my_data будут выводиться переменные $title и $content. Однако это вовсе не так. На самом деле шаблон откомпилируется схематично следующим образом:

{$title}

{$content}
То есть по сути внутри контейнера данных ничего нет! А переменные, которые в исходном шаблоне как бы относились к контейнеру данных my_data, на самом деле в откомпилированном шаблоне относятся именно к корневому контейнеру данных. Здесь есть 2 решения: * Вынести наверх, до тега * Создать отдельный шаблон (например, layout.html), который будет содержать разметку, а обворачивание в этот шаблон сделать уже внутри Первый вариант будет выглядеть сдедующим образом (изменится только текущий шаблон): {$title} {$content} Самый большой недостаток этого подхода - это то, что теперь весь шаблон заключен в активный компонент тега , то есть мы как бы имеем теперь 2 корневых шаблона. Это может повлять на работу некоторых шаблонов, которые выводили некоторые переменные, считая что текущий контейнер будет глобальным, например, {$meta_keywords} вместо {$#meta_keywords}. Второй способ более правильный, но требует выделения еще одного шаблона. Вот как будут выглядеть все наши шаблоны: Базовый шаблон **page.html** Шаблон **layout.html**

{$title}

{$content}
И наш текущий шаблон: {$title} {$content} Теперь все будет работать как ожидается.