WordPress underscore template

The last few posts I’ve mentioned diving into creating an underscore theme. There is now one core ticket I’ve been keeping an eye on and will continue to do so until it is resolved.

Since the last post I did install the REST API plugin so this now means I am one step closer to converting this site to a project site. Yes. Expect things to break here this year. 🙂

A few links

In my quest for theming in JS I came a across few links that helped shed some light as to how WordPress does things not only within the customizer but in the admin areas. I love reading the inline docs for that reason. There are a few other tutorials and posts I came across that may also help others out there:

Great and wonderful resources. So let us write a little code!

JS code

One of the first things we want to do is enqueue our main JavaScript file and add jQuery and underscore as a dependency.

add_action( 'wp_enqueue_scripts', function(){
	wp_enqueue_style( 'default', get_stylesheet_uri() );
	
	$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
	
	wp_enqueue_script( 'jmc-main-js', get_template_directory_uri() . '/js/main.js', array( 'jquery', 'underscore' ) );
	wp_localize_script( 'jmc-main-js', 'site', array(
		'restURL' => get_rest_url(),
		'name' => get_bloginfo( 'name', 'display' ),
	) );
});

Awesome! In the above we have enqueued our stylesheet and our main JavaScript file we will use. In our file we will use something like:

_.templateSettings = {
	evaluate:    /<#([\s\S]+?)#>/g,
	interpolate: /\{\{\{([\s\S]+?)\}\}\}/g,
	escape:      /\{\{([^\}]+?)\}\}(?!\})/g,
};

// Site name
jQuery( document ).ready( function($){
	var titletemplate = _.template( $( '#site-title' ).html() );
	$( '#masthead ' ).append( titletemplate({name: site.name }) );
});

In the JS you see we create a new variable ( titletemplate ) and it stores the markup from the site-title jQuery is getting. From there we can now use the append() method to add the newly created markup to our #masthead element. What does it look like?

<script id="site-title" type="text/template">
	<h1 class="site-name">{{{ name }}}</h1>
</script>

Fairly neat, yeah? We have now attached the site’s name via JavaScript. Yeah, not a huge deal since you can also do it with basic PHP and WordPress core functions but it is something neat to experiment with specially if you want to use some neat JavaScript/CSS effects.

That’s great but what about posts? Because we declared our templateSettings in the global space we can use the core methods of handling underscore templates. So rather than using:

  • <%= %>
  • <%- %>
  • <% %>

Why the change?

There may be a few that ask why using mustache style and not ERB that underscore uses. The reason is because in some cases PHP will be setup to use ASP style tags and we don’t want any issues to arise from that. So, rather than having to list off another dependency and another file be loaded we instead use that small snippet that makes it work. That code can be found in the wp-util file and if we look at the code we can see what it is doing:

wp.template = _.memoize(function ( id ) {
	var compiled,
		/*
		 * Underscore's default ERB-style templates are incompatible with PHP
		 * when asp_tags is enabled, so WordPress uses Mustache-inspired templating syntax.
		 *
		 * @see trac ticket #22344.
		 */
		options = {
			evaluate:    /<#([\s\S]+?)#>/g,
			interpolate: /\{\{\{([\s\S]+?)\}\}\}/g,
			escape:      /\{\{([^\}]+?)\}\}(?!\})/g,
			variable:    'data'
		};

	return function ( data ) {
		compiled = compiled || _.template( $( '#tmpl-' + id ).html(), null, options );
		return compiled( data );
	};
});

It is simply passing an object with a few options. And with that we can now use:

  • {{ name }} for escaped data
  • {{{ name }}} for un-escaped data
  • <# _.each() #> to evaluate the code

So now if we had to iterate over an array of posts we can use underscore’s each() method to do so. It could look something like:

<script id="post-tpl" type="text/template">
<# _.each( posts, function( post ){ #>
	<article class="post" id="{{ post.id }}">
		<h2 class="post-title">{{{ post.title.rendered }}}</h2>
	</article>
<# }) #>
</script>

Great!

I will end it by noting that I am not using the tmpl- prefix because I am using underscore’s template() method and passing it our template directly. One advantage, I guess. So, go. Explore, break things, and learn from it!

Published by

Jose

Born in El Salvador. Loves to read, write, draw, paint, build, test, typography, hike, photography, art, design, sewing, and many other things.