wp.template — HTML templates for JavaScript in WordPress

WordPress utilizes templates everywhere, and JavaScript is no exception. In this article, we will talk about the built-in capability in WordPress to create HTML templates that can then be used in JS. Creating and using such templates is very simple, much like many other aspects of WordPress.

There are many ways to create templates in JavaScript, and there is even a separate specification called Mustache for them. It is implemented in many languages, including JavaScript. For example, the library Handlebars uses this specification and even extends it slightly. Or the popular mini-library Underscore.

Since version 3.5, WordPress has a convenient template engine for JS in its core. For example, it is used in the admin area when creating blocks for the media uploader. It is based on the aforementioned Underscore library, with slightly modified syntax to better comply with the Mustache specification.

To create templates in WordPress, there is a method called wp.template

wp.template( id )

Creates a template object from HTML code. To get the ready-to-use HTML code in JS, you need to pass data to the created object for template filling.

Returns

Function. A function to which you need to pass data, which will then be interpolated in the created HTML template.

Usage
var template = wp.template( id );
var HTML = template( data );
id(string)

The identifier of the HTML element that contains the HTML code of the template. The HTML element must have the specified id attribute with the prefix tmpl-.

For example, if you specify foo here, then the HTML element must have id id="tmpl-foo".

data(object)
JS data object that will be used to fill the template. For example: { text: 'Hello' }.

wp.template is defined in the file wp-includes/js/wp-util.js.

Template Filling (Interpolation)

  • {{{data.unescaped}}} — unescaped data.
  • {{data.escaped}} — escaped data.
  • <# logic #> — process js (eval).
Prefix data.

data in the template is an object of raw data. In the template, you should use the key data.

To match the structure of data returned by the functions: wp_send_json_success() and wp_send_json_error(), wp.template wraps all received data in the data variable. Therefore, before each parameter in the template, you need to specify data., otherwise we will get an error: {property} is not defined.

<script type="text/html" id="tmpl-my-template">
   <p>Correctly {{{data.name}}}</p>
   <p>Incorrectly {{{name}}}</p>
</script>
Template Example
<script type="text/html" id="tmpl-my-template">

	<p>This will be simply displayed.</p>

	<p>Display the value of the escapedValue variable {{data.escapedValue}}.</p>

	<p>If the data contains markup, display it without escaping:</p>
	{{{data.unescapedValue}}}

	<p>When you need to perform some logic.</p>
	<# if ( data.trueValue ) { #>
		<p> Will be displayed only if data.trueValue = true.</p>
	<# } #>

</script>

Template Creation and Generation

Template Creation

To ensure that the template does not appear in the DOM tree, it is customary to create it in a script tag with the type type="text/html".

<script type="text/html" id="tmpl-my-template">
   <p>Hello {{{data.name}}}</p>
</script>

The id attribute should start with tmpl-, and everything after this prefix will be used in the function wp.template( 'my-template' ).

Creating a template in a script tag is a hack that is perfect for creating an HTML element that is not used by the browser. When an unknown type is specified for the browser, it simply ignores the html tag, which is what we need.

The template can also be created in any other HTML element (for example, in <div>, which can then be hidden), the only thing needed is to specify the id attribute.

There is also a special HTML tag <template> for creating templates, however, it is not supported in IE. But in general, it is quite relevant.

Template Generation

wp.template() returns a function, so do not attempt to pass the result into an HTML element or output the result to the console. Usually, the result of wp.template() is passed into a variable, and then this variable is used as a function, and data is passed to it to fill the template.

Example (template is specified above)

<!-- html -->
<div class="my-element"></div>
// JS
var template = wp.template( 'my-template' )
var data     = { name: "Victor" }

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

As a result, we will get in HTML:

<div class="my-element">
	<p>Hello Victor</p>
</div>

Example of Commenting on AJAX with Template Usage

Create a template and include the script in the theme file 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
}

Then you need to create a JS script that will send the data of a new comment via AJAX and receive the added comment object.

Then this object needs to be passed to the template and the received HTML code needs to be added to the DOM:

var singleTemplate = wp.template( 'comment-single' ), // our template
var $comments      = jQuery('.commets_wrap'),              // container with comments
var $commentForm   = jQuery('#respond')                    // comment form

// function to handle AJAX response
function commentSuccess( data ){
	// create HTML using the template
	$comments.append( singleTemplate( data ) );

	// reset the form
	$commentForm.get(0).reset();
}

For a detailed breakdown of the example, see the article wp.template for front end templating in WordPress.