FREELessons: 29Length: 8 hours

Next lesson playing in 5 seconds

  • Overview
  • Transcript

4.2 Say Hello to Handlebars

Today, we'll focus less on jQuery, and more on a third-party templating solution, called Handlebars (an extension of Mustache). It's important to remember that jQuery isn't some magical black box that is capable of everything. It handles a few things extremely well, such as working with the DOM, and performing AJAX requests. However, for other needs, such as code organization or templating, it's better to refer to third party tools.

When it comes to templating, Handlebars is easily one of the most popular options. I'll show you how to use it in your projects.

4.2 Say Hello to Handlebars

[SOUND] The interesting thing about today's lesson is that we're not exclusively focusing on jQuery. And this is something that we'll be taking a look at more and more. It's important to remember that jQuery is not this magical black box that is capable of everything. It does a couple things really, really well. Maybe better than any other library. And those things are working and manipulating the DOM, and working with asynchronous operations like Ajax, jQuery is perfect for that. However, for other things such as structuring your code or templating, you'll want to take a look at different tools, tools that were made specifically for that purpose. So while in the last lesson we focused on a makeshift templating system, for more control you can take a look at a variety of third-party tools. In this case we'll take a look at Handlebars, which is my favorite. It's very popular. And you can see it, it more or less follows the same system that we did in the previous lesson but it's much, much more powerful. So if we take a look at getting started, you see the same thing. You create your template and you use this curly brace notation to designate where you want your information to display. So let's jump in and see how we can use mustache. I'll go to the top. I'll click on the GitHub link. And we can see installing is easy. Simply download the package from GitHub. So for now we will click on this larger version. And we'll just link directly to that. You might wanna download this for your own projects, though. All right. So I've copied that link. I'm gonna go into Sublime Text. And we'll add a new script reference. And I'll paste that link in like so. Now, we're ready to get started using handlebars. The next step is to create our template itself, and we did this in the previous lesson, and it more or less follows the same process. Now, I've saved this to a snippet, and you probably should, too, in your favorite editor. Now, you'll notice that we give it an id template. That's fine for now. And once again, we give it a type of text/x-handlebars-template. This is just a convention, what they want you to use, and that's fine. Now, within here, we can create our template as we normally would. So maybe we're going to have some tweets. So we'll say ul tweets. This is where the tweets should be displayed. And what we'll do here, is to make it a little easier to understand, we're going to place the script within here. And that way it's easy to tell that this template corresponds to the tweets. And now within here, we can create our template. So, we'll have the tweet itself, something like that. But we should also have a thumbnail for the author, so we'll place that at the top, and we'll say thumbnail. And then, maybe within a paragraph tag, we'll have the tweet itself. Okay. And we'll keep it simple for now. So now we need to figure out, how can we use handlebars to bind data? So right here at the bottom we'll create a self-invoking anonymous function. Now I wanna take a quick note: I've gotten a lot of questions of why we're using a self-invoking anonymous function rather than document.ready. I guess you've read books that say you need to do this. And this is fine, but what you need to know is document.ready is a way of saying, when the DOM is ready to be manipulated, then execute this callback function. And that's why we always use that when we're in the head of our document. Because at that point let's say you were trying to access tweets. Well from here, tweets hasn't been loaded yet. So we can't access it. That's why we use document.ready. However, if we were to place a script even below it right here, at this point we have loaded the ul with a class of tweets, and now we can access that in the DOM. So when your code is placed at the bottom, you don't really need to use document.ready. You only would really use that when it's placed within the head of your document. So the rule of thumb is when possible, always import your scripts at the bottom. Sometimes you can't. For example, if you're bringing in a tool like modernizr, you'll want to include modernizr at the top to keep from flashes and things of that nature. But for other things, especially responding to events and stuff like that, definitely place that at the bottom so that your pages will load more quickly. Now with that out of the way, let's get back into it. And we need to create some data. So we'll say data like so. And for now we'll have thumbnail. And you know what? Because we're making this up, let's just do author at the top, and we'll place that within an h2. That way I don't have to hunt down an image. But later we will take advantage of the Twitter API itself, and we can do that. This just makes it easier on me. And we'll say, author, Jeffrey Way and the tweet is 30 Days to Learn jQuery Rocks. Okay, so now we have this data and we want to bind it to our template. Now the way we do that is we say, handlebars. When we import the handlebars.js script we now have this new global called Handlebars. And we can say .compile. And what it wants to receive is a path to where your template is stored. So it wants to receive script with an id of template and it wants us to grab that out. Now you can either store this within a string, as I'll show you shortly. Or, you can do what we've done here and store it as an HTML template. So we'll simply grab that out, template, and I wanna grab the HTML out of it. I don't wanna grab the note itself, I wanna grab this right here. Now, we've compiled that, let's store that within a variable called template, and we'll simply console.log template to see what we're working with here. If I view this in Chrome, you can see what template is now equal to is this function where we pass the context. The context is going to be your object, your data that you're trying to bind. So now that we know that, let's come back. And we're going to trigger our new function, template. And we're going to pass in data. Now let's store this within a variable just for now called temp, temporary variable. And we'll console.log that one more time and now you can see we've updated our template. So, what this does is we say, handlebars, take the template that we've created right here and compile it, and that gives us this new function that we can trigger. Then when we've called the function, we pass in our object or our data, and then it takes that data and dynamically attaches it to our little variables here within the curly braces. And then at that point we would append it wherever we need to. If we need to add it to the body, you could say document.body.append the results of this function. Now we reload and we get that on the page. But we know that we actually want to place it within the ul with a class of tweets. So instead we can change that to ul.tweets. Reload the page. And now let's view this. And you can see we have our ul with a class of tweets. We have our template. And that's a nice way for the web designer or whoever's not working with the JavaScript as much to tell, okay, within here we're going to have a list item. We're going to have a heading2 and a paragraph. And that's a lot easier to style, rather than using string concatenation to create that HTML manually, in which case the web designer doesn't really know what you're working with until he views it in the browser. So then our code compiles and we throw our list item into the DOM where we asked. So now at this point if we want to have an array of objects, let's go and do what we did last time. I will copy this object, paste it in again, and we'll change the author to John Doe. Now, if I come back and reload the page, you're not gonna get anything. And this is where it's going to be a little different from our makeshift solution. Because we have more control, we need to be a little more specific. At this point now, we have passed an array. So right now it's trying to bind an author property to the array. But it's not available. So the easiest way to get around this is we filter through the items in the array. So at the top I'm simply going to say, for each, notice I'm using this pound sign. This is how we can do if or unless or each statements. And we'll say for each, and we're going to say this at this point. Because this array, if this were a property and you had a property called data and its value was equal to this array, you could say for each data, and then you could access author and tweet for each one of them. But in this case, this object isn't assigned to a property name. So we're going to say for each this, and this will refer to what we have passed. So we have this array. This is all the template has to work with. So we're going to say for each this, referring to the array, for each item in the array. And now we need to designate the end. If you're familiar with PHP, a for statement or for each, very much the same thing. And notice we close it by doing forward slash and then the name. So curly brace, curly brace, forward slash, each. And now you'll see that, that is loaded successfully. Now what if we come back here and this tweet contains HTML? So, we'll wrap 30 Days within strong tags. Now watch what happens. We reload. You'll see that handlebars automatically takes care of the escaping. Now, in this case, if you want to actually take that HTML and render it, in that case, right at the top, rather than two curly braces, you would wrap it within three on each side. And now you'll see that it's no longer escaped, that's a good thing to know. Now let's come back to our object, and let's say we're going to have an option for the age. I don't know why you would, but just something that we can work with. Well, I'm 27. But, we'll say that John Doe did not provide his age or we don't have that information available. So, right at the top, we could say, within a span tag, age. Something like that. We'll go to the top, style and we'll say h2 span. Color is gray, font size is 0.8 ems. Now you will see that, as we expect, my age has been added. But if we inspect the element, and you'll see for John Doe, here is John Doe. We still created that span tag, even though that information was not available. So wouldn't it be cool to say if there is an age, only on that condition should we render this span. And we can do that. Right here, surrounding the span tag we'll say, if age and then close our if. Just like that. One more time, reload, and let's see if it worked. We'll click on John Doe. Open it up and notice the span tag is not rendering. But we do have that dash, so we would probably want to take that dash out and place it like so. There we go. Now I have an age, but John Doe does not. And as soon as we add one for John Doe, age 45, now that's been added on. Now I encourage you to take a look at the documentation. We're not going to cover everything, I want to give you a quick dose of what you will do in most situations. And then for anything specific you can refer here for lots of examples. Let's take a look at a couple more things. We know that we can do if. We know that we can filter through an array. We can also do things like unless. Now, Ruby developers will be familiar with unless. Maybe if you're from PHP or you stick with HTML and JavaScript you won't. Unless is the exact some thing of if not. So we know we can say, like in JavaScript or PHP, if not something, Then do this. Well that's the same thing in some languages as saying unless something, than do this. Now with handlebars, we can do the same thing. So to give you an example of this, let's add something to our template that we know we're not going to receive. So I will say unless quote, and we'll close that out. If there's not a quote, then let's say, this is a little ridiculous, but we will say author does not have a quote. So let's try that out. Reload the page. Neither of them have a quote so that's been added. But if we add a quote, we'll add one for me. Never, ever, ever, ever give up. You'll see that it's no longer displaying for me because unless if not. This is the same thing as saying, if there is not a quote, then add an h5. Well, we go to me. Nope, there's a quote so we're not going to add that. But for the next one nope, there's not a quote. So in that case we show the h5. Or if you'd like to change that to an if else, you could say if quote then show the quote. And then to do the else, we would do else, show the h5, and then we close out our if statement. Same thing, reload the page. And we can see never ever, ever give up. Oops, I have an extra curly brace right there. Yes we do, sorry about that. One more time, never ever, ever give up. But John Doe does not, so we see author does not have a quote. So you can see how easy it is to create complex structures using templating. And imagine if you had to use maybe something like an array or string concatenation to build all of this up. You'd create lots of really messy JavaScript, and that makes your project much more difficult to maintain. So lastly let's see about how we can register our own helpers. So at the bottom what we'll do here is we'll change author from a full name to an object. And we'll have first is Jeffrey. And last is Way. And then I'll do the same thing for John Doe. There we go. And now we wanna create a custom, essentially a helper function that will combine both of those. So right here we'll say handlebars. And I'm just doing all of this procedurally. You can organize your code a little bit better once you know how to use this. And we'll say handlebars.registerHelper. And what is this helper going to be called? We'll call it fullName. And that's how we will reference it within our template. And that will be a function. Now this function should receive something. In this case, we're going to pass the author to it. So I will add that in, like so. And now I simply wanna return author.first and a space, and then author.last. We're essentially returning Jeffrey. And a space and Way. So now, if we come back here, we filter through our each statement. I'll get rid of this if statement cuz we don't really need it here. And now we'll say, for the author, if we load this in the browser, you'll see that we get object Object, because that's not going to work anymore. So what we'll change this to is fullName. And we'll pass in the author as a parameter. Reload and now we get Jeffrey Way. So, let's go over this. We created a new helper and we called it fullName. Create a helper, call it fullName. And next we add a space and pass in author, and this is the argument that we're going to send into that function. So we're going to send in the contents of this author property which is an object. So now, author, right here, is equal to this object right there. And then we simply take the first name, add a space, take the last name, and that gets returned. And then, subsequently, that is placed within the h2 tag. Now, if we want to add the age on there as well, you could say, plus a dash and then add on the age. And then you would simply replace that like so. Get rid of that. We'll do the same thing for John Doe. And finally let's make sure we reference that with author.age. So, let's come back to Chrome, and there we go, Jeffrey Way, 27, John Doe, 45. Okay, so, this has been a, a very simple example, but it's important to understand just the basic concepts of how you would use the template, how you can determine whether or not to display certain markup or data based upon whether it's available within the context. You often see this referred to as context and that's fine. That works, too. It's just a name. So in the next lesson we're going to take things even further and we're going to work with the actual Twitter API so that we can query it, return some JSON, filter through that JSON and attach it to our template. So that'll be a lot of fun. I'll see you then.

Back to the top