wp.template — HTML шаблоны для Javascript в WordPress

В WordPress повсюду используются шаблоны и Javascript там не исключение. В этой заметке поговорим про встроенную в WordPress возможность создавать HTML шаблоны, которые затем можно использовать в JS. Создаются и используются такие шаблоны очень просто, впрочем как и многое другое в WordPress.

Есть много способов создавать шаблоны в Javascript, для них даже придумана отдельная спецификация именуемая Mustache. Она реализована на многих языках, включая Javascript. Например, библиотека Handlebars использует эту спецификацию и даже немного её расширяет. Или популярная мини-библиотека Underscore.

С версии 3.5 WordPress уже имеет в своем ядре удобный шаблонизатор для JS. Он например используется в админке при создании блоков для медиа-загрузчика. В основе лежит вышеупомянутая библиотека Underscore, синтаксис немного переделан, чтобы больше соответствовать спецификации Mustache.

Для создания шаблонов в WordPress есть метод wp.template

wp.template( id )

Создает объект шаблона из HTML кода. Чтобы получить готовый HTML код для использования в JS, в созданный объект нужно передать данные для заполнения шаблона.

Возвращает

Function. Функцию, в которую нужно передать данные, которые затем будут интерполированы в созданном HTML шаблоне.

Использование
var template = wp.template( id );
var HTML = template( data );
id(строка)

Идентификатор HTML элемента который содержит HTML код шаблона. HTML элемент должен иметь указанный тут атрибут id с префиксом tmpl-.

Например, если тут указать foo, то HTML элемент должен иметь id id="tmpl-foo".

data(объект)
JS объект данных, которые будут использованы для заполнения шаблона. Например: { text: 'Привет' }.

wp.template определяется в файле wp-includes/js/wp-util.js.

Заполнение шаблона (интерполяция)

  • {{{data.unescaped}}} — неочищенные данные.
  • {{data.escaped}} — очищенные данные.
  • <# логика #> — обработать js (eval).
Префикс data.

data в шаблоне — это объект исходных данных. В шаблоне нужно использовать именно ключ data.

Чтобы соответствовать структуре данных возвращаемых функциями: wp_send_json_success() и wp_send_json_error(), wp.template оборачивает все полученные данные в переменную data. Поэтому перед каждым параметром в шаблоне нужно указывать data., иначе мы получим ошибку: {property} is not defined.

<script type="text/html" id="tmpl-my-template">
   <p>Правильно {{{data.name}}}</p>
   <p>Неправильно {{{name}}}</p>
</script>
Пример шаблона
<script type="text/html" id="tmpl-my-template">

	<p>Это будет просто выведено.</p>

	<p>Выведем значение переменной escapedValue {{data.escapedValue}}.</p>

	<p>Если данные содержат разметку, выводим без экранирования:</p>
	{{{data.unescapedValue}}}

	<p>Когда нужно выполнить какую-то логику.</p>
	<# if ( data.trueValue ) { #>
		<p> Будет выведено, только если data.trueValue = true.</p>
	<# } #>

</script>

Создание и генерация шаблона

Создание шаблона

Чтобы шаблон никак не фигурировал в DOM дереве, его принято создавать в теге script с указанием типа type="text/html".

<script type="text/html" id="tmpl-my-template">
   <p>Привет {{{data.name}}}</p>
</script>

Атрибут id должен начинаться с tmpl-, все что после этого префикса будет затем использовано в функции wp.template( 'my-template' ).

Создание шаблона в теге script это хак, который отлично подходит для создания html элемента, который никак не используется браузером. Когда указан непонятный для браузера тип он просто игнорирует html тег, а это нам и нужно.

Шаблон также можно создать в любом другом HTML элементе (например в <div>, который затем можно скрыть), единственное что нужно это указать id атрибут.

Также для создания шаблонов есть специальный HTML тег <template>, однако он не поддерживается в IE. Но в целом он довольно актуален.

Генерация шаблона

wp.template() возвращает функцию, поэтому не пытайтесь передать результат в html элемент или вывести результат в консоль. Обычно результат wp.template() передается в переменную, а затем эта переменная используется как функция и в неё передаются данные, которыми должен быть заполнен шаблон.

Пример (шаблон указан выше)

<!-- html -->
<div class="my-element"></div>
// JS
var template = wp.template( 'my-template' )
var data     = { name: "Виктор" }

jQuery('.my-element').html( template( data ) )

В результате получим в HTML:

<div class="my-element">
	<p>Привет Виктор</p>
</div>

Пример комментирования на AJAX с использование шаблона

Создаем шаблон и подключаем скрипт в файле темы functions.php:

<?php

add_action( 'wp_enqueue_scripts', 'my_scripts_method' );
add_action( 'wp_footer', 'lw_comment_templates', 30 );

function my_scripts_method(){
	wp_enqueue_script( 'wp-util' );
}

function lw_comment_templates(){
	?>
	<script type="text/html" id="tmpl-comment-single">
	  <li class="{{data.comment_class}}" id="li-comment-{{data.comment_ID}}">
		<div id="comment-{{data.comment_ID}}" class="comment">
		  <div class="comment-meta comment-author vcard">
			{{{data.gravatar}}}
			<div class="comment-meta-content">
			  <cite class="fn">
				<# if ( data.comment_author_url ) { #>
				  <a href="{{data.comment_author_url}}" rel="nofollow" class="url">
				<# } #>
				{{data.comment_author}}
				<# if ( data.comment_author_url ) { #>
				  </a>
				<# } #>
			  </cite>
			  <p>
				<a href="<?php the_permalink(); ?>#comment-{{data.comment_ID}}">
				  {{data.date_formatted}} at {{data.time_formatted}}
				</a>
			  </p>
			</div> <!-- /comment-meta-content -->
		  </div> <!-- /comment-meta -->
		  <div class="comment-content post-content">
			<# if ( "1" !== data.comment_approved ) { #>
			  <p class="comment-awaiting-moderation"><?php _e( "Awaiting moderation", "wilson" ); ?></p>
			<# } #>
			{{{data.content_formatted}}}
		  </div><!-- /comment-content -->
		</div><!-- /comment-## -->
	  </li>
	  <!-- #comment-## -->
	</script>
	<?php
}

Далее нужно создать JS скрипт, который будет отправлять данные нового комментария по AJAX и получать объект добавленного комментария.

Затем этот объект нужно передать в шаблон и добавить полученный HTML код в DOM:

var singleTemplate = wp.template( 'comment-single' ), // наш шаблон
var $comments      = $('.commets_wrap'),              // контейнер с комментариями
var $commentForm   = $('#respond')                    // форма комментирования

// функция обработки AJAX ответа
function commentSuccess( data ){
	// создаем HTML по шаблону
	$comments.append( singleTemplate( data ) );

	// сбрасываем форму
	$commentForm.get(0).reset();
}

Подробный разбор примера смотрите в статье wp.template for front end templating in WordPress (англ).