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!

A few core changes

In the last post I mentioned I wanted to dive a little bit into using Backbone and Underscore for a theme. I still am pursuing that. I’ve made some progress on that front so that’s a good thing.

There is one thing that does need to change a little bit. The libraries used in core. Currently they are at version 1.2.3 and 1.8.3 for Backbone and Underscore respectively. Core is a little outdated and is in need of an update. Yes, there is a core ticket for backbone and underscore on trac but they do need testing.

That’s great!

Now this means I get to set up my test site and try to break things. I’m really looking forward to this part. Yes, I like to figure out where things break and why a lot.

The other reason I’m happy is because earlier today I realized that I didn’t have the WP-API plugin on this site. I know, I know. Core will be using this down the road but this is one thing that really needed to be installed on here for the longest time. I don’t really know how I never installed it long ago but that is now fixed.

I guess the next stage will be in writing out a quick post on my learning of underscore and templating. I did learn a few things while diving into the core files and undercores documentation.

The big lesson learned was that the following code is used in core and can be used in a theme in order to declare your own version of templating rather than having to add wp-util as a dependency.

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