• Meteor

Build a Simple Application Part 2

From the class:  Getting Started with Meteor

In this video, we'll add some styling to our application, we'll look at more advanced uses of helpers, and we'll look at event handlers. Let's start off by adding a package called Bootstrap. Bootstrap is a CSS framework made by the people from Twitter, and it helps us to quickly style our application.

You can see simply by adding the package in the right, the look and feel of the app changes a little bit. Next, let's add another package called Less. This makes it easier to write dynamic style sheets.

Then I'll change the CSS file to Less, and then we'll open up Vim and I'll paste in some CSS. I'm not going to go through each one of these style rules here because in this track, I'd prefer to focus on the application. But the source code is available, so you can go and take a look, and feel free to ask any questions.

So when I save that, you could see the styling and the app changes right away. Next up, let's fill out our To Do item template a little bit more. Right now we're just showing a subject, but I would also like to show whether or not the task is done.

So to do that, I'll create an input of type checkbox, and I'll name it Is Done so we can reference it later. And then I'm going to do something a little special-- to tell whether or not the checkbox is checked, I'm going to use a helper that we'll define in a minute called Is Done Checked, and I'm going to include that as an attribute of the input.

And then around the subject, let's just wrap it in a class called Subject, and then I'll make it look a little bit nicer. So next, let's go define that Is Done Checked helper. So we'll create another set of template helpers, but this time on the To Do item. And we'll create a helper called Is Done Checked, and it'll just be a function that returns the string checked if the task is done or the to do is done. Otherwise, it just returns an empty string.

And so notice that the data context inside of this function is the to do item itself. So that's what this points to, is the To Do document.

Next, let's define our first event handler. What we want to do is when the user clicks on the Is Done checkbox, we want to update the underlying data. So to create an event handler, I can call the events method of the To Do item template, and the events object will take the selector as the key, and as the value, it'll be the event handler.

In this case, we want to respond to the click event where the name is Done, and the function will take two parameters-- the event object, and then a template object as the second.

Next, what we'll do is I'm just going to create an ID variable and assign that to Once again, this inside of this function points to the data context, which is the particular to do item.

Next, we'll find out whether or not the task is done. I'll call the find method on the template, and you can think of this as similar to a find query using jQuery. So I'll look for an element that is of type input, and then I'll see whether or not it's checked or not.

Finally, what we need to do is update our data. So I'll call the update method, and the document that we're going to update has an ID of the one that we just grabbed. And then we'll use the Mongo set modifier and we'll set the Is Done property to whatever the value is that we got from our checkbox.

Great, so now the underlying data should be updated depending upon whether I select the checkbox or unselect it. Let's verify this. In the JavaScript console below, I'll call the find one method on our To Dos collection.

That'll just return the top item in the list. You can see it's our first To Do, and the is done property is set to false. Now if I check the checkbox, our event handler should get triggered and it should update the data setting Is Done to true. And there, you can see the Is Done property is indeed set to true.

Next up, this application wouldn't be very useful if we couldn't create new to do items, so let's do that now. I'll jump back over to the HTML file, and let's create a new template for creating new to do items.

We'll render this template out at the top of our To Dos panel, and I'll call the template Create To Do Item. Now let's go and define that template.

I've scrolled down and pasted in a template so that we can get started, and you can see that it just renders Create To Do Item to the page. Now let's fill out this template a little. I'm going to start by creating a form that has a class of Create To Do, and then inside of that form, we'll create an input of type text. Then I'll give it a placeholder, and you can see the new text box up at the top.

Next up, we need to go back to our JavaScript and define the event handler for creating a new to do, so we can respond to the form submit event and then add the new to do to our To Dos collection. So I'll switch back over to our JavaScript file, and let's add an event handler for the submit event of the form that we just created.

OK, let's create an event map on the Create To Do item template. So I'll call the events method again, and this time, we're going to respond to the submit form event. And the first thing I'll do inside of this event handler is to prevent the default behavior. That's because typically when you submit a form, the browser will post back to the server, and we don't want that to happen.

Next, I'll create a variable called Subject so that we can grab the subject from the input field. So I'm using the find method again of the template, and then just using regular HTML element methods and the value attribute to grab the value.

Next, what we need to do is to call the insert method of our To Dos collection. So just like working with regular Mongo, except for working in the browser. So for the subject, we'll use the subject that was just grabbed from the input value, and then we'll just give it a timestamp. And by default, we'll say that the task is not done, and that will be enough for now. And then finally once that To Do item is inserted, let's grab the form itself and clear it.

And I'll save my file again, and over in the right, it looks like I have some kind of syntax error. So what we can do when we get syntax errors is I'll refresh the page and I should get an error message here that shows me what line that syntax error's on. So you can see in this case, it's line on 40, and it looks like I forgot to assign this using the equals symbol. So let me come back here and refresh this browser again, and now it seems to be working.

Let's see whether we can actually create a new to do. Great, it looks like it's working properly. Now, one thing I've noticed is I might want new to dos to appear at the top of the list, not at the bottom.

So if I go back up to the items helper where we return the list, what I can do here is say I want to find all the to dos, so I'm not going to provide a particular selector, but then I want to sort by the Created At date in descending order. So I'll use negative 1. And now if I save, you should see the second to do appears at the top of the list instead of at the bottom.

Another thing I'd like to do here is to style the row differently if the task is done or not. Namely, I'd like to put a strikethrough or a line through the task when it's marked as complete. So to do that, we can dynamically add a class to the row depending upon whether it's done or not. Let's go back to our HTML file and down in the list item area, I'm going to add a dynamic class. We'll call it Is Done Class.

And just like before, I'm going to go back to the JavaScript file and we can define that new helper on the To Dos panel called Is Done Class. And what we'll do is say if the task is done, then return the Done class. Otherwise, just an empty string.

Now, over in the browser when I complete a task, it gets the Done class, and that's what causes this strikethrough styling. And if I inspect the element, you can come down and see the class has been defined right here. And if I uncheck, you see the Done class gets taken away.

The reason that this works this way is because Meteor templates are reactive. That means if the underlying data changes, the template knows to redraw itself based on the changed data.

Before we conclude this video, let's add one more user interface element or control to this page. That's the To Dos count. So back in the HTML file, would I'd like to do is to show a count template at the bottom here.

So I will call that To Dos Count, and then we can jump down to the bottom and define the template. To save some time, I created the To Dos Count template, and now we'll fill in its HTML. I'll give it a class of To Dos Count, and then we'll create a helper called Completed Count, which will give us the number of tasks that are complete.

And then we'll show a divide sign and we'll create another helper called Total Count, which will be the total number of tasks. So now the user interface looks a little bit crazy because we haven't added these helper methods, so I'll go back to the JavaScript file and we'll add them now. Down at the bottom, I'll reference the To Dos Count template, and we'll call the Helpers method to create some helpers. And the first helper will be Completed Count, and that will return the result of calling find, and will look for tasks where the is done property is set to true.

And then on the resulting cursor, we'll call the count method. Then I'll create the next helper, which is Total Count. And what that will do is we'll call the find method, and this will be all of the tasks, and we'll call the count method on that. So now you can see we have one out of two to dos completed, and I can change that value by checking and unchecking the various to dos.

So in this video, we looked at how Meteor templates are reactive, and then we looked at some more advanced use cases for helpers and how to use event handlers on templates. Next up, we'll take a closer look at how data can be published and subscribed to.