IntroductionWelcome| 00:00 | (music playing)
| | 00:04 | Hello, I'm Joe LeBlanc.
| | 00:06 | Welcome to Up and Running with Backbone.js.
| | 00:09 | Backbone provides the tools you need to
write fully browser-based applications.
| | 00:14 | We're going to take a look at how to
do these using techniques like defining
| | 00:18 | your own URLs without going to the
server, automatically updating markup when
| | 00:23 | data changes, sorting data in the
front-end, and using your server to get the
| | 00:29 | most out of Backbone.
| | 00:31 | Backbone is going to change the
way you write web applications.
| | 00:34 | So let's get Up and Running with Backbone.js.
| | Collapse this transcript |
| What you should know| 00:00 | There are a few things you should be
familiar with before learning about Backbone.
| | 00:04 | First, there's JavaScript.
| | 00:06 | JavaScript is the language
that Backbone is written in.
| | 00:09 | You can learn more about JavaScript
in JavaScript Essential Training on the
| | 00:13 | lynda.com Online Training Library.
| | 00:17 | Next, there is jQuery.
| | 00:19 | Backbone uses jQuery or a
library with a jQuery-compatible API.
| | 00:24 | You can learn more about
jQuery in jQuery Essential Training.
| | 00:27 | We'll also be using
Twitter Bootstrap in this course.
| | 00:31 | We'll be using Bootstrap
to help with our markup.
| | 00:35 | You can learn more about it in
Up and Running with Bootstrap.
| | 00:38 | Finally, a general knowledge
of HTTP will also be useful.
| | 00:43 | JavaScript, jQuery, and HTTP are the
fundamental technologies behind Backbone.
| | 00:48 | The more you know about them,
the easier Backbone will be to learn.
| | Collapse this transcript |
| Using the exercise files| 00:00 | This course includes exercise
files you can use to follow along.
| | 00:04 | The exercise files are organized so you can
jump into the code used for a specific video.
| | 00:09 | Let's take a look at the exercise files now.
| | 00:12 | The exercise files are organized by chapter.
| | 00:16 | Inside of each chapter are
folders for the specific videos.
| | 00:20 | Each video folder has a start folder,
a final folder, and sometimes has
| | 00:26 | a snippets.txt file.
| | 00:28 | Snippets.txt will include pieces of code
we'll be pasting into the files that are in start.
| | 00:36 | Each start folder includes a server.js file.
| | 00:40 | You'll want to make sure that the server is
started before you proceed with the video.
| | 00:44 | We'll be learning more about
this server in the next chapter.
| | 00:48 | You can use the code in the final folder
to compare your work with the end result.
| | 00:53 | With the exercise file structure in
mind, you can now watch any video in this
| | 00:57 | course and follow along.
| | Collapse this transcript |
|
|
1. Configuring a New Backbone ProjectWhy Backbone?| 00:00 | If you have tried to build large web
applications in a web browser without
| | 00:04 | a framework like Backbone, you've probably
seen the complexity of your code increase rapidly.
| | 00:11 | Let's take a look at some of the
concepts Backbone brings to simplify things.
| | 00:16 | One of the primary concepts that
Backbone brings is a separation of the data
| | 00:21 | from the presentation of that data.
| | 00:24 | If you're familiar with jQuery, you may
have written code like this in the past.
| | 00:28 | On line 1, we're calling the getJSON method.
| | 00:32 | The first argument we're
passing into getJSON is script.php.
| | 00:37 | We're expecting that script.php is a
file on the server that's going to return
| | 00:42 | some JSON data for us.
| | 00:45 | The second argument that's on
line two is a callback function.
| | 00:49 | This callback function takes the JSON
data that's returned from script.php
| | 00:54 | as its only argument.
| | 00:57 | Inside of this function, starting
on line 3, we're using this data.
| | 01:02 | As soon as the data is ready, we find
the HTML element with an ID of content.
| | 01:07 | We then set the HTML of that element
with the name, price, and description
| | 01:13 | that's found in the data.
| | 01:15 | Although this code is easy to
write, there's a problem with it.
| | 01:18 | The problem is that we're combining the HTML
markup with the action of getting the data.
| | 01:25 | If we wanted to get the data from another
source, we wouldn't be able to reuse this code.
| | 01:30 | The DOM manipulation is stuck in the
callback function that starts on line 2.
| | 01:35 | Using a framework like Backbone
helps us separate these two actions.
| | 01:40 | Another major concept of
Backbone is the fact that it has an
| | 01:43 | event-based architecture.
| | 01:45 | Instead of tying specific callbacks
to specific events, objects in Backbone
| | 01:50 | can emit events, then other objects can choose
to listen to those events and act accordingly.
| | 01:57 | Reusable JavaScript objects are
another thing that Backbone brings.
| | 02:01 | Instead of hiding functionality in
callback functions, we can create a reusable
| | 02:05 | JavaScript object and
use it over and over again.
| | 02:09 | Finally, Backbone allows
for front-end navigation.
| | 02:13 | We can eliminate trips to the server by
reading the URL and acting accordingly.
| | 02:18 | Backbone provides fundamental
structure for a front-end web application.
| | 02:23 | Using a framework like Backbone helps
you separate data from markup, create
| | 02:28 | reusable code, and decouple
callback functions from specific events.
| | Collapse this transcript |
| Downloading Backbone and dependencies| 00:00 | Backbone is a lightweight JavaScript library.
| | 00:03 | There are only a couple of essential
dependencies, but there are few pieces
| | 00:08 | we'll want to download
for a full web application.
| | 00:11 | So, let's get started with the downloading.
| | 00:13 | First, there's Backbone, and on the
page here, there are three different
| | 00:19 | versions you can download:
| | 00:20 | there's the Development Version, the
Production Version, and the Edge Version.
| | 00:26 | The version we'll want to
download is the Production Version.
| | 00:29 | This code is mostly unreadable.
| | 00:33 | All the whitespace has been stripped
away, and some of the variable names have
| | 00:37 | been changed to shorter ones.
| | 00:40 | This code has undergone a
process called minification.
| | 00:43 | Minification aims to make the file
size as small as possible so that it
| | 00:48 | downloads as quickly as possible.
| | 00:51 | Let's save this file now.
| | 00:54 | First, let's create a folder for our project.
| | 00:56 | I'm going to name it Restaurant.
| | 01:00 | Now that we have the folder, click Save.
| | 01:05 | Next, let's download Underscore.
| | 01:08 | Underscore is the only
hard dependency of Backbone.
| | 01:12 | Underscore also has a
Development, Production, and Edge Version.
| | 01:16 | Again, we just want the Production Version.
| | 01:20 | Just like the Production Version of
Backbone, the Production Version of
| | 01:24 | Underscore has been minified.
| | 01:26 | Let's save this file as well.
| | 01:32 | Next, let's download jQuery.
| | 01:35 | Backbone does not specifically
depend on jQuery, but it needs the DOM
| | 01:40 | manipulation functionality of jQuery.
| | 01:43 | You can use any library that
has a jQuery-compatible API.
| | 01:47 | I'm choosing jQuery because it's
very familiar and it's well tested.
| | 01:54 | Click on Download jQuery and then select
Download the Compressed Production jQuery.
| | 02:01 | Just like Backbone and Underscore,
the Production Version of jQuery has been minified.
| | 02:06 | Let's save this file.
| | 02:13 | Next, let's download Bootstrap.
| | 02:15 | Backbone does not depend on Bootstrap at all.
| | 02:18 | We'll be using Bootstrap in this
project to provide us with some basic CSS.
| | 02:25 | Bootstrap comes in a ZIP file, so
let's move this to the right place.
| | 02:30 | I'm going to move this ZIP file to the
desktop and then move Bootstrap.zip into
| | 02:35 | the Restaurant folder.
| | 02:40 | You can learn more about Bootstrap in
the Up and Running with Bootstrap video in
| | 02:44 | the lynda.com online training library.
| | 02:49 | Finally, make sure you have Node.js installed.
| | 02:53 | We'll be using Node.js to power a server
that we'll be using throughout this course.
| | 02:58 | If you don't already have Node.js on
your computer, look at Node.js First Look
| | 03:03 | and specifically take the
Installing Node chapter.
| | 03:07 | While this course will be using this
specific set of libraries, it's entirely
| | 03:11 | possible to swap them out for
ones that suit your preferences.
| | Collapse this transcript |
| Starting a Node server| 00:00 | Node is an environment that
runs JavaScript without a browser.
| | 00:04 | Throughout this course, we'll be
using Node to power an example server.
| | 00:07 | Although it is possible to use
Backbone without a server, Backbone is
| | 00:11 | designed with one in mind.
| | 00:12 | So first, let's go to the exercise files.
| | 00:15 | Go to Chapter 01, video 03,
and we a have Start folder here.
| | 00:20 | This Start folder has all of the
assets that were downloaded in the previous
| | 00:24 | video into the Restaurant folder.
| | 00:26 | I've just moved them here.
| | 00:28 | In addition to those files, there's
also a server.js file, a package.json
| | 00:33 | file, and then a Public folder that's empty
and a data folder that has menu-items.json.
| | 00:41 | We're now going to use Node to start
server.js, which will give us an HTTP server.
| | 00:47 | Go to Applications and go to Utilities.
Then go to Terminal and double-click on it.
| | 00:55 | We'll be using Terminal a lot in this
course, so go to the doc and right-click
| | 01:00 | and then click Options > Keep in Dock.
| | 01:03 | If you're using a PC, have a look at
Node.js First Look for instructions on how
| | 01:08 | to use Node on the command line on a PC.
| | 01:11 | Now, we're going to navigate
to the ExerciseFiles folder.
| | 01:14 | I'm going to use tab
completion to help me get there quicker.
| | 01:18 | Type in "cd" and then space and then type
a capital D and a lower case e and then
| | 01:24 | Tab, which brings up Desktop. Then type
in capital E and tab again, then 01/03.
| | 01:36 | Finally, type in "cd" and space "start."
| | 01:40 | From here, I'm going to type in "npm install."
| | 01:45 | This is going to install all the
dependencies that our project has.
| | 01:49 | These dependencies are
listed in the package.json file.
| | 01:53 | Now finally, I'm going to start the server.
Type in "node" and then space "server.js."
| | 02:01 | It now says that the server is
ready at localhost on port 3000.
| | 02:06 | I'm going to copy this address, open
up my web browser, and then go there.
| | 02:13 | You'll notice that it's returned a
json string saying status is not valid.
| | 02:18 | That's because we currently don't have
an index.html file in our Public folder.
| | 02:23 | However, there are other routes
that were defined in the server file.
| | 02:28 | If we go back to the ExerciseFiles
and go to the Start folder and then open
| | 02:32 | server.js, you'll notice that
there is a route defined at items.
| | 02:38 | Let's go to that route now.
| | 02:42 | The items route returns all the items
that are in our data file, and we can go to
| | 02:47 | specific items as well.
Add /cheeseburger onto the end and then hit Enter.
| | 02:54 | This now pulls up the JSON
object for the cheeseburger.
| | 02:58 | We can also stop the server.
| | 03:00 | Go back to Terminal and hit Ctrl+C.
If we try refreshing the page, it will give
| | 03:07 | us an error because the
server is no longer running.
| | 03:10 | Let's start the server again.
| | 03:12 | I'm going to press up, which is going
to pull up the last command that I typed,
| | 03:16 | and now when I hit enter,
it starts the server again.
| | 03:20 | If I go back to the browser and hit
Refresh, it now pulls up our data again.
| | 03:24 | Node provides a way of
creating a simple HTTP server.
| | 03:27 | In this course, we'll use this server
to help us get the most out of Backbone.
| | 03:31 | Make sure the server is
running as you follow along.
| | Collapse this transcript |
| Assembling application boilerplates| 00:00 | Now that we have a web server ready to
deliver files and data, let's arrange the
| | 00:04 | JavaScript libraries we
downloaded earlier into a boilerplate.
| | 00:08 | After we arrange this boilerplate,
we'll be able to reuse it to start new
| | 00:12 | projects in the future.
| | 00:14 | First, let's navigate to the ExerciseFiles.
| | 00:19 | Inside of the Public folder,
we've added an index.html file.
| | 00:24 | This index.html file references several
JavaScript files, as well as some CSS files.
| | 00:31 | Let's move these files into the correct places.
| | 00:34 | First, go to the Public folder.
| | 00:36 | We're going to create three folders here:
one called js, one called css, and one called img.
| | 00:48 | Next, inside of the js folder,
we're going to create a subfolder called lib.
| | 00:54 | I like to arrange my JavaScript folder
in this way so that all of the external
| | 00:59 | libraries I'm using are in one
folder, and then the rest of the folder is
| | 01:02 | dedicated to my actual application.
| | 01:05 | You don't necessarily have to lay out your
project this way, but I find this helpful.
| | 01:09 | Next, let's move JavaScript
files into that lib Folder.
| | 01:13 | We have Underscore, jQuery, and Backbone.
| | 01:18 | Let's move all of those into the lib folder.
| | 01:25 | Next, we have Bootstrap.
| | 01:26 | Bootstrap comes in a ZIP file.
| | 01:28 | I'm going to double-click it to
uncompress and then move the assets into
| | 01:32 | the correct places.
| | 01:34 | Now notice it comes with the js Folder.
| | 01:37 | Even though it comes with a js Folder,
we're going to move bootstrap.min.js
| | 01:41 | into that lib Folder.
| | 01:42 | Now, let's go back to the Bootstrap folder
and then we're going to use the CSS and images.
| | 01:52 | I'm going to use the minified versions
of the CSS. And then back in the Bootstrap
| | 02:00 | folder, we have the images.
| | 02:03 | These images are used to power the icons.
| | 02:10 | Now, we can remove bootstrap.zip,
as well as the Bootstrap folder.
| | 02:13 | So now, with all of these assets in place, we can
start up the server and load it in the browser.
| | 02:21 | Go to the Terminal.
| | 02:23 | Now, I'm going to change the
directory to the ExerciseFiles.
| | 02:26 | Type cd, space, capital D, then e, and Tab
for desktop, capital E, lowercase x, and
| | 02:34 | then Tab for ExerciseFiles, then 01/
04/start, then type node server.js.
| | 02:46 | The server is now ready on port 3000 so
I'm going to go there in my web browser.
| | 02:51 | You'll notice that this time,
instead of getting an error, we get the Off
| | 02:54 | the backbone homepage.
| | 02:56 | This is because we have an
index.html file in the Public folder.
| | 03:00 | With all these tools arranged, we now
have an application boilerplate ready
| | 03:03 | to serve our needs.
| | 03:05 | This is the bare minimum necessary
to build a substantial web application
| | 03:08 | using Backbone. A copy of this
boilerplate can be made to get started quickly
| | 03:13 | with other projects.
| | Collapse this transcript |
| Building routes| 00:00 | Backbone is designed so that you
could do as much work in the front-end as
| | 00:03 | possible so that you can
minimize trips back to the web server.
| | 00:07 | With Backbone, you can
define a front-end URL structure.
| | 00:11 | This allows visitors to navigate and
share links just as they would with a
| | 00:14 | server-oriented application.
| | 00:16 | Let's go to the exercise files.
| | 00:19 | We've now added an app.js
file inside of the js folder.
| | 00:24 | So let's update
index.html to reference this file.
| | 00:32 | Open snippets.txt in your
exercise files and copy the script tag from
| | 00:39 | snippets.txt into index.html.
| | 00:43 | Next, we're going to add some navigation.
| | 00:47 | Copy this unordered list from
snippets.txt into the first div in the document.
| | 00:54 | Now, save the file.
| | 00:55 | Let's start the server.
Change directory to Desktop/ExerciseFiles/01/05/start,
| | 01:07 | then type Node server.js.
| | 01:15 | We now have the same index.html file
as before, only this time we have some
| | 01:19 | navigation and as we click on
the links, different things appear.
| | 01:26 | You'll notice that if I change garden-salad
for anything else, it simply appears there.
| | 01:33 | Let's take a look at app.js
and see how this is working.
| | 01:39 | So first, on line 1, we're
calling Backbone.Router.extend.
| | 01:43 | The extend function in Backbone
allows us to create objects that have
| | 01:47 | class-like behavior.
| | 01:49 | So, we're using the extend function to
create an object called AppRouter, and
| | 01:53 | we're going to use AppRouter later on.
| | 01:57 | Next, we have an object property called Routes.
| | 02:00 | The properties of this object correlate
to the URLs that appear in the browser.
| | 02:05 | The object values correlate
to functions in the router.
| | 02:08 | So for instance, on line 4 we have
menu-items/new as the object property of
| | 02:14 | routes, and then item form is the value.
| | 02:17 | This matches up to itemForm on line 16.
| | 02:21 | So whenever menu-items/new gets called in
the browser, the itemForm function is executed.
| | 02:28 | All three of these functions are
doing very simple DOM manipulation.
| | 02:33 | On line 5, we have menu-items/colon-item.
| | 02:37 | The colon allows us to pass
in variables through the URL.
| | 02:42 | On line 12, that item is
being passed into the function.
| | 02:45 | So then we can use that
item within the function.
| | 02:49 | Finally, on line 21, we're
creating a new object based on AppRouter.
| | 02:54 | And then after that, on line 23, we're
using jQuery's ready function to make sure
| | 02:59 | that the JavaScript is
executed after the DOM is ready.
| | 03:03 | In this case, we're
calling Backbone.history.start.
| | 03:07 | This function sends an event to the
router and tells it to start working.
| | 03:11 | One thing you'll notice is that
we have a hash in the URL.
| | 03:15 | This hash makes it possible for us to
intercept the URL requests so that they
| | 03:20 | don't go to the server.
| | 03:21 | Backbone's router is a simple and powerful
way of defining URLs for your application.
| | 03:27 | It's possible to extract variables
from URLs, as well as enter the application
| | 03:31 | from multiple routes.
| | Collapse this transcript |
|
|
2. ViewsCreating a view| 00:00 | Separating data from HTML markup is one of
the fundamental concepts behind using Backbone.
| | 00:06 | Let's create a view that will help us
display some data while keeping this separation.
| | 00:13 | Now, let's take a look at the exercise files.
| | 00:17 | This time our public folder has a
folder called Photos, and then inside of JS
| | 00:22 | we have a folder called Views.
| | 00:24 | Let's add this view code to index.html.
| | 00:31 | Open up snippets.txt and
copy the script tag, then add it.
| | 00:38 | Be sure you add it above app.js.
| | 00:42 | Now, let's go to app.js.
| | 00:44 | You'll notice that in the previous
version of the code, we're simply outputting
| | 00:52 | the name of the item when we navigate there.
| | 00:54 | Our item details function on line 12
is currently just taking the name of the
| | 00:59 | item that's passed in and
outputting it in the DOM.
| | 01:03 | Let's update this with some
code that uses a view instead.
| | 01:07 | Go back to snippets.txt and copy
these lines, from lines five to thirteen.
| | 01:14 | Then go to the current item details
function and replace the DOM manipulation
| | 01:19 | with this new code.
| | 01:21 | You'll notice that we're now creating a
new view with menu item details, passing
| | 01:26 | in the name of the item, and then using
Entree as a default for category and
| | 01:31 | no-image.jpeg as the image path default.
| | 01:34 | Then on line 21, we're
doing DOM manipulation again.
| | 01:37 | We're calling the render function of the
view object and then retrieving the EL property.
| | 01:43 | Let's take a look at how
this works in the browser.
| | 01:45 | When we navigate to Garden Salad,
it's showing the title garden-salad with
| | 01:54 | Entree as a category and our no-image picture.
| | 01:58 | If we want to, we can go
back and change the image path.
| | 02:01 | When we hit refresh, the garden-salad appears.
| | 02:07 | Let's take a look at the view
code that's powering all of this.
| | 02:11 | Go back to the exercise files and open
up MenuItemDetails.js in the Views Folder.
| | 02:19 | On line 1, we're creating a new
object called MenuItemDetails, and we're
| | 02:24 | creating it using Backbone.View.extend.
| | 02:27 | This is similar to the router that
we created earlier; only this time
| | 02:31 | we're creating a view.
| | 02:33 | Next, we're defining a
render function on line two.
| | 02:37 | This render function continues on line
three, where we're concatenating a string
| | 02:41 | using the data that we're supplying.
| | 02:44 | Notice that we're calling this on line four.
| | 02:48 | This is referring to the view object.
| | 02:51 | If we go back to app.js, you'll notice
that name, category, and image path get
| | 02:57 | passed into the view as an object.
| | 02:59 | Those same three properties are
available in the options object of this.
| | 03:05 | Then on line 9, we're calling this
$el. $el is a short cut to the jQuery
| | 03:13 | object representing the element.
| | 03:16 | Finally, we're calling the HTML
function on the element and passing in the
| | 03:21 | string that we've concatenated.
| | 03:23 | Finally on line 10, we're returning This.
| | 03:26 | Returning the This object allows
us to chain calls to the view.
| | 03:31 | Backbone's views make it possible to
completely separate markup from data.
| | 03:35 | With this separation in place, we
now have reusable code for displaying
| | 03:39 | data about a menu item.
| | Collapse this transcript |
| Templating views| 00:00 | When you're working with HTML markup,
it's essential to properly escape data so
| | 00:04 | that special characters like
ampersands don't break the rendering.
| | 00:08 | Also, overly concatenated strings of
markup can be difficult to read after a while.
| | 00:13 | Templating libraries, such as
Handlebars, solve both of these problems.
| | 00:18 | Now, while we're going to use
Handlebars for the templating in this project,
| | 00:21 | you don't necessarily have to use Handlebars
as your templating engine for your project.
| | 00:26 | The syntax for Handlebars involves curly braces.
| | 00:30 | Whenever you have a variable that you
want to escape, enclose that variable name
| | 00:34 | in two sets of curly braces.
| | 00:37 | We're going to be using this syntax in our
project. So, let's download Handlebars now.
| | 00:43 | Let's save this file.
| | 00:44 | Go to the exercise files and then
navigate to our JavaScript libraries folder.
| | 00:54 | Now that we've saved the file,
let's include it in our index.html file.
| | 01:03 | In snippets.txt, there's a script tag
that we can copy directly into index.html.
| | 01:12 | I like to group all of
libraries in one spot in the head tag.
| | 01:16 | Next, let's update our
view code to use handlebars.
| | 01:21 | Navigate to the js/views Folder
and then open up menuitemdetails.js.
| | 01:30 | We're going to replace the render function
in MenuItemDetails with these two properties.
| | 01:39 | On line 2, we have a property called Template.
| | 01:42 | We're using Handlebars' Compile
method to create a template function.
| | 01:46 | You'll notice that we have three
variables here, for name, category, and image path.
| | 01:51 | They are enclosed in double curly braces.
| | 01:54 | The double curly braces will ensure
that all of the markup is escaped.
| | 01:58 | Handlebars.compile actually returns a
function, so we're going to call that
| | 02:02 | function within our render function.
| | 02:05 | On line 11, we're calling
this.template and then passing in this.options.
| | 02:11 | The options object will have all
the properties we need to supply a name,
| | 02:15 | category, and image path.
| | 02:18 | Finally, the results of
this.template are passed into the HTML function
| | 02:22 | that's also on line 11.
| | 02:24 | And then on line 12, we're returning this,
just as we did on the previous video.
| | 02:30 | Returning this allows us
to chain function calls.
| | 02:34 | Now, let's load our
project again in the browser.
| | 02:39 | Navigate to garden-salad.
You'll notice we have the same output as before.
| | 02:45 | Even though we have the same output,
the source code is much cleaner.
| | 02:49 | Templating libraries like handlebars
reinforce the separation between your
| | 02:53 | presentation markup and application logic.
| | 02:56 | Using a templating library will make
your markup easier to read while keeping
| | 03:00 | your code properly decoupled.
| | Collapse this transcript |
| Reusing views| 00:00 | Once you've initialized a view,
you can reuse it for new data.
| | 00:04 | Let's take the menu
itemDetails view and reuse it.
| | 00:08 | Navigate to the Exercise Files.
| | 00:12 | Open up app.js in the js folder.
| | 00:14 | You'll notice on line 13
we're declaring a new view.
| | 00:19 | This new view is declared every time
the itemDetails function is called.
| | 00:24 | This is wasteful and will eventually
degrade the performance of our application.
| | 00:29 | Let's replace this code with
something that's more efficient.
| | 00:33 | Open up snippets.txt.
| | 00:37 | First, there's an initialize function.
| | 00:40 | Copy this function and
paste it underneath the routes.
| | 00:46 | The initialize function is only going to be
called when the app router object is initialized.
| | 00:51 | This time we're declaring a new
MenuItemDetails view and setting it to
| | 00:55 | this.menuItemView on line 9.
| | 00:59 | Because we're declaring the view here
and setting it right away, we're able to
| | 01:03 | reuse it throughout the rest of the app router.
| | 01:05 | Now, let's go back to the snippets
file and copy in another function.
| | 01:09 | Copy the itemDetails function.
| | 01:16 | Now replace the existing itemDetails
function with the one from snippets.txt.
| | 01:21 | On line 22, we're referencing
this.menuItemView, and then we're setting the name
| | 01:26 | property of the options object.
| | 01:29 | This way, each time we call the
itemDetails function, we're simply reusing the
| | 01:33 | same view but setting the property differently.
| | 01:35 | Finally, on line 23, we're calling
the render function of the MenuItemView
| | 01:40 | that's associated with this router
and then getting the EL property.
| | 01:45 | Save the file and go to the browser.
| | 01:48 | Make sure the server is already running.
| | 01:53 | Navigate to the Garden Salad item.
| | 01:55 | You'll notice that the
same screen appears as before.
| | 01:59 | If we go instead to /menu items/
cheeseburger, you'll notice that the title
| | 02:06 | updated but we still have the same image.
| | 02:09 | That's because we've
hard-coded the image for the moment.
| | 02:13 | However, we're reusing the view, so
we're not creating a new view every time we
| | 02:17 | load a different item.
| | 02:19 | Creating a new view object for
every rendering is not necessary.
| | 02:23 | Application performance can be
improved by reusing the view object.
| | 02:27 | Set the view with new
data, then re-render the view.
| | Collapse this transcript |
| Generating list views| 00:00 | In addition to displaying single
records, most web applications will also
| | 00:04 | display a list of them.
| | 00:06 | Generating a list view in Backbone is
similar to creating a single view, but the
| | 00:10 | supporting data structure is different.
| | 00:12 | Well, let's go to the exercise files.
| | 00:17 | There's a new file in the Views folder.
Open menu.js and let's have a look.
| | 00:25 | This view is similar to the other
views that we have for single items.
| | 00:30 | On line five, we're using some
new syntax that Handlebars provides.
| | 00:35 | Think of the each command
on line 5 as an HTML tag.
| | 00:38 | It starts of with each
and then ends with a /each.
| | 00:44 | We're also specifying the name of
the variable we want to pass into each.
| | 00:48 | Finally, we're outputting this.
| | 00:52 | In this case, we're
expecting items to be an array.
| | 00:55 | Each item in the array
will be represented by this.
| | 00:59 | And then finally, the render
function renders this view.
| | 01:03 | On line 10, we're passing
this.options into the template function that's
| | 01:08 | assigned to this view.
| | 01:09 | We're expecting that this.options has
a property named items and that that
| | 01:14 | property will be an array.
| | 01:17 | Now, let's add this view to our project.
| | 01:22 | Open snippets.txt and you'll notice we
have a script tag at the top. Copy the
| | 01:29 | script tag from line 3 and go to
the index.html file in public. Sdd the
| | 01:39 | script tag on line 11.
| | 01:41 | Next, we need to update app.js.
| | 01:48 | The first thing we need to do is add
the view into the initialize function.
| | 01:52 | Go back to the snippets file and copy
everything from line 9 to line 17.
| | 01:58 | Now, go back to app.js and
make some room underneath line 14.
| | 02:05 | This code, starting on line 16,
is initializing the menuView.
| | 02:10 | We're passing in an object with a property
named items, and this property is an array.
| | 02:16 | Finally, we need to update our list function.
| | 02:19 | Scroll down to line 27.
| | 02:22 | At the moment, we're just outputting
list screen in the element with ID of app.
| | 02:27 | Let's go back to the snippets
file and replace this function.
| | 02:32 | Copy everything from line 20 to line 22
and then go back to app.js and then just
| | 02:38 | replace lines 27 through 29.
| | 02:40 | Now, we're taking menuView and calling the
render method and then getting the EL property.
| | 02:48 | After saving the file, go to your
web browser and load up the site.
| | 02:52 | Make sure your server is already running.
| | 02:57 | Now, you'll notice we have Garden Salad,
Pizza, and Cheesecake rendering as a list.
| | 03:01 | Generating list views is very
similar to generating views for
| | 03:04 | individual records.
| | 03:06 | Data for list views is delivered
through arrays, and Handlebars provide syntax
| | 03:10 | for looping over the array elements.
| | Collapse this transcript |
| Challenge: Linking routes to views| 00:00 | For this challenge, link to a
single category of menu items.
| | 00:04 | The view will have a fixed set of items,
but the category name should reflect the URL.
| | 00:09 | The first objective is to create a
reusable view that can handle both a category
| | 00:13 | name and the photos of several items.
| | 00:16 | Use these images to test your view.
| | 00:19 | Next, make a route where the category
view can be reached, along with a way of
| | 00:23 | specifying the category name.
| | 00:26 | Finally, add a link to the
category view in the main navigation.
| | 00:30 | Start this challenge using the exercise files.
| | 00:33 | It should take about ten minutes to complete.
| | 00:36 | In the solution, I'll show you how
I made this category view, as well as
| | 00:40 | something to keep in mind when building URLS.
| | Collapse this transcript |
| Solution: Linking routes to views| 00:00 | So here is my solution to the challenge.
| | 00:02 | The link Sides now
appears in the main navigation.
| | 00:06 | When I click Sides, I'm taken to the
new category view, displaying carrots,
| | 00:11 | green beans, and mashed potatoes.
| | 00:13 | I can change the last segment of
the URL to desserts and the view
| | 00:17 | updates accordingly.
| | 00:20 | Let's take a look at the
code making this happen.
| | 00:24 | First, I created
menucategory.js in the Views folder.
| | 00:29 | This is defining a new view
called MenuCategoryView on line 1.
| | 00:32 | Then I begin to lay out the template.
| | 00:37 | On line 3, I have a
header displaying the category.
| | 00:40 | Then on line 5, I'm cycling over all
the photos and displaying them one by one.
| | 00:48 | Finally, I have a render
function starting on line 9.
| | 00:51 | On line 10, I'm passing the view
options into the template function that got
| | 00:55 | compiled, and then I'm taking the results
of that and setting the HTML content of
| | 01:01 | the element of this view.
| | 01:03 | Then I added this view to index.html.
| | 01:06 | On line 12, I added a script tag
pointing to js/views/menucategory.js.
| | 01:14 | While I was in the
index.html, I also added the link.
| | 01:17 | Notice the link points to #/categories/sides.
| | 01:22 | It's essential to have the hash in here.
| | 01:26 | Let's see what happens when we try
to go to the URL without the slash.
| | 01:33 | This route went to the
server instead of to Backbone.
| | 01:36 | Since the server does not know about
the category/sides route, it's returning
| | 01:40 | status of "Not found."
| | 01:44 | Adding the hash into the URL
allows Backbone to intercept the route.
| | 01:50 | Finally, let's go to app.js.
| | 01:55 | First, on line 27,
I started a new menu category view.
| | 02:00 | On line 28, I passed in an object.
| | 02:03 | This object has two properties.
| | 02:05 | On line 29, I specified a category.
| | 02:09 | And on line 30, I passed
in an array called images.
| | 02:13 | Note that we never see Entree in our display.
| | 02:17 | I simply defined a default here so that
when I look at this code later, I know
| | 02:21 | what the view is expecting.
| | 02:26 | Then on line 6, I added a new route.
| | 02:29 | I have categories/category,
pointing into categoryDetails.
| | 02:34 | Category is a variable that we can
use in the categoryDetails function.
| | 02:39 | Let's go to the categoryDetails function.
| | 02:43 | On line 48, the categoryDetails function
takes the category as a single argument.
| | 02:49 | The router is going to pass
this argument into the function.
| | 02:52 | Then on line 49, we're setting the
category property of the options object of
| | 02:58 | the view to category.
| | 03:01 | Finally, on line 50, we're finding the
element with ID of app and then setting
| | 03:06 | the HTML to the rendered
output of the MenuCategoryView.
| | 03:09 | So when you're creating new views,
be sure to make it reusable by keeping
| | 03:14 | your data separate.
| | 03:15 | You can always define a set of
default values to pass in for testing.
| | 03:19 | Also, pay attention to your URLs and
make sure you aren't missing the hash.
| | Collapse this transcript |
|
|
3. ModelsDefining models| 00:00 | In most applications, you will want to keep
track of data in specific recurring formats.
| | 00:05 | For example, items in this
Restaurant menu will always have a title, a
| | 00:10 | category, and a photo.
| | 00:12 | A model can be used to enforce this
specific format for every menu item.
| | 00:17 | We've added a model to this project,
so let's take a look at it in the ExerciseFiles.
| | 00:21 | Inside of js, there's a folder called
models, and inside of models, there's a
| | 00:26 | file named menuitem.js.
| | 00:29 | The model is being defined just
like the views in the router were.
| | 00:34 | On line 1, we're calling the extend
method of Backbone_Model, and this is giving
| | 00:39 | us all the functionality of Backbone's model
while allowing us to further define the object.
| | 00:45 | On line 2, we're setting defaults.
| | 00:49 | Inside this defaults object, we have the
field names as well as the default values.
| | 00:55 | Now, let's add this model to our project.
| | 00:57 | Open up snippets.txt.
| | 01:01 | First, we have a script tag for index.html.
| | 01:08 | Copy the script tag from line
3 and then paste it onto line 11.
| | 01:14 | Next, we have some changes to make to app.js.
| | 01:21 | Back in snippets.txt, copy everything
from line 9 to 14 and then go back to
| | 01:27 | app.js and replace lines 9 through 14.
| | 01:30 | So now, instead of hard coding
everything to the garden-salad, we're
| | 01:35 | first declaring a model.
| | 01:37 | After the model is set into the
Router on line 9, we're then declaring a
| | 01:42 | new view on line 10.
| | 01:44 | We're now passing this model into the view on
line 12 instead of passing in an object literal.
| | 01:50 | We also need to update the itemDetails function.
| | 01:54 | Go back to snippets.txt and copy line 17.
| | 01:59 | Now, replace line 32.
| | 02:02 | Now, whenever itemDetails is called,
the item name is going to be passed in on
| | 02:07 | line 31 and then that item name is
going to be set into the model on line 32.
| | 02:14 | Finally, we need to change
the menu item details view.
| | 02:17 | Open up menuitemdetails.js.
| | 02:20 | On line 11, we're currently
passing this.options into the template.
| | 02:25 | We now want to pass the
model attributes in instead.
| | 02:28 | Go back to snippets.txt.
| | 02:31 | Copy line 21, then go back to menuitemdetails.js.
| | 02:37 | Now, replace line 11.
| | 02:39 | We're now setting the
template with this.model.attributes.
| | 02:43 | Now, let's go to the web browser.
| | 02:45 | Make sure your server is already running.
| | 02:48 | I'm going to clear out this window and open
up a new one to make sure we get the new code.
| | 02:53 | Now, navigate to garden-salad.
| | 02:56 | You'll notice that the name got set, but
the category is still entrees and the
| | 03:00 | photo is still the empty plate.
| | 03:02 | This is okay for now because
we'll be changing it later.
| | 03:05 | Models help to keep your
data structure consistent.
| | 03:08 | They allow you to specify defaults and
keep the data in the attributes property.
| | 03:13 | This keeps the data out of the views
options and in the model, where it belongs.
| | Collapse this transcript |
| Listening to models| 00:00 | Separating the data and presentation
layers guarantees that the view will work
| | 00:04 | regardless of which model we couple with it.
| | 00:07 | However, the data in the model will
change as the application gets used.
| | 00:11 | We need to tell the view that the
model has new data to be rendered.
| | 00:15 | So at the moment, we have
the original model and view.
| | 00:19 | The garden-salad title is
being rendered as the name.
| | 00:23 | However, entrees and the empty plate are
being used as the defaults from the model.
| | 00:29 | Let's try to change one of these
values now and see if it gets updated.
| | 00:33 | I'm going to pull up the JavaScript Console.
| | 00:36 | You can do this in Google Chrome by
going to View > Developer > JavaScript Console.
| | 00:42 | Now let's try to use the
set method of the model.
| | 00:46 | Type in app.menuItemModel.set.
The first argument we're going to pass in is
| | 00:55 | category, and we're passing that in as a
string. Then the second argument we're
| | 01:01 | going to pass in is deserts.
| | 01:04 | Now when I hit Enter, you'll
notice here that the model changed.
| | 01:10 | The category is set to Desserts; however,
in the markup, it still says entrees.
| | 01:16 | We need to find a way of letting the view
know that it's time to update the markup.
| | 01:20 | Let's go to the exercise files.
| | 01:26 | Open snippets.txt. You'll notice on
line four that we're calling This.ListenTo.
| | 01:35 | This is a function that
we're going to add to our view.
| | 01:38 | This.listenTo allows us to pass in a
model, and then it also allows us to pass in
| | 01:44 | an event to listen to.
| | 01:46 | And then finally, the third argument is
the function to call when that event occurs.
| | 01:52 | Let's add this initialize function to our view.
| | 01:54 | Go to js/views/menuitemdetails.js.
| | 02:01 | Now we're going to go back to snippets.txt
and copy everything from line 3 to 5.
| | 02:07 | Finally, make some room in
menuitemdetails.js and paste in the
| | 02:12 | initialize function.
| | 02:15 | So now what is happening on line 11
is we're listening whenever the model
| | 02:19 | emits a change event.
| | 02:21 | When that occurs, we're going
to call the render function.
| | 02:24 | Save this file and go back to the browser.
| | 02:26 | I'm going to close this window and open a
new one to make sure we get the new code.
| | 02:33 | Now let's go to the garden-salad menu item.
| | 02:36 | I'm going to pull up the
JavaScript Console again.
| | 02:41 | Finally, let's set the model properties.
| | 02:45 | I'm going to set the category again.
| | 02:52 | You'll notice now that not only did the
model change, but the view changed as well.
| | 02:58 | The view is able to listen to the
model event and then update itself.
| | 03:02 | By using events, views in Backbone can
listen to the models attached to them.
| | 03:06 | This makes it possible to update the
markup without creating a dependency on the
| | 03:11 | specific model used.
| | 03:13 | The model simply emits events as
it changes and the view listens for
| | 03:17 | those events.
| | Collapse this transcript |
| Loading remote data| 00:00 | Many web applications present a list of
records where a title can be clicked and
| | 00:04 | that specific record is displayed.
| | 00:06 | By setting up the model appropriately,
the data for this single record can be
| | 00:10 | loaded from the server on
demand, then rendered by a view.
| | 00:14 | So at the moment I have my
server up and running, and I've gone to
| | 00:17 | /items/cheeseburger.
| | 00:21 | This server is designed to deliver JSON data
for any URL that is attached to the items route.
| | 00:28 | This record has the URL and the name of
the item, as well as the category and the
| | 00:33 | image that we'll want to use for the menu item.
| | 00:37 | Let's set up our model so it loads
the data directly from the server.
| | 00:41 | Open up snippets.txt.
| | 00:46 | First, we're going to modify MenuItem.js.
| | 00:50 | Go to models/MenuItem.js.
| | 00:53 | Then go back to snippets.txt and copy line 10.
| | 00:58 | Then in MenuItem.js, paste this in on line 2.
| | 01:03 | We're now specifying the
URL route for this model.
| | 01:06 | The model now knows to use /items as the
route for all of the URLs for fetching data.
| | 01:13 | We now need to update our router to
load the individual items. Open up app.js.
| | 01:21 | On Line 32, our current itemDetails
function just sets the name.
| | 01:26 | What we want to do instead is
load the data from the server.
| | 01:30 | Go back to snippets.txt.
| | 01:32 | Copy lines 5 and 6 and then replace line 32.
| | 01:37 | So now on line 32, instead of
setting the name, we're setting the id.
| | 01:43 | id is a special property in Backbone models.
| | 01:47 | The id is appended to the URL
route and then that URL is loaded.
| | 01:51 | However, the data is not loaded right away.
| | 01:54 | It will only be loaded when we
call the fetch method on line 33.
| | 01:58 | Now that we have this code in
place, let's go back to the browser.
| | 02:04 | First, click on Garden salad.
| | 02:07 | Now the title, the category, and
the photo are all loading correctly.
| | 02:11 | This is because we got the data from the server.
| | 02:14 | Now let's try loading another record.
| | 02:17 | I'm going to /menu-items/cheeseburger.
| | 02:21 | Again instead of pulling default
values, it went to the server and got the
| | 02:25 | cheeseburger record.
| | 02:26 | So now we have the correct title, the
correct category, and the correct photo.
| | 02:30 | Finally, we can also do this from the console.
| | 02:33 | Go to View > Developer > JavaScript Console.
| | 02:38 | I'm typing in app.menuItemModel.set, and
now I'm going to set the id. This time
| | 02:47 | I'm going to load the pizza.
| | 02:50 | Now you'll notice that setting
the model didn't load the data.
| | 02:54 | We still need to call the fetch method.
| | 02:56 | So now type app.menuItemModel.fetch.
So now the pizza record has loaded.
| | 03:07 | Backbone is designed to easily handle
data stored on the server. By defining
| | 03:11 | the URL route property in your model
and then setting an id, Backbone can
| | 03:16 | fetch the data for you.
| | Collapse this transcript |
| Challenge: Displaying updated data| 00:00 | For this challenge, make it possible
to update the list screen in real time.
| | 00:05 | Earlier in this chapter we made the view
re-render itself whenever the model data changed.
| | 00:10 | The list screen does not currently have a
model, so updating the view is difficult.
| | 00:15 | The first objective is to create a
model for handling data on the list screen.
| | 00:20 | Next, we want to make sure that
the model has the current list.
| | 00:24 | That's the Garden Salad, Pizza, and Cheesecake.
| | 00:28 | The final objective is to make sure the view
gets updated whenever data in the model changes.
| | 00:34 | Start this challenge using the exercise files.
| | 00:37 | It should take about ten minutes to complete.
| | 00:40 | In the solution, I'll show how I
made list updates possible, as well as a
| | 00:44 | pitfall to avoid.
| | Collapse this transcript |
| Solution: Displaying updated data| 00:00 | So here is my solution to the challenge.
| | 00:02 | I currently have all three original
items in the list, and now I'm going to
| | 00:07 | update this list from the Google Chrome console.
| | 00:10 | I'm pressing up because I'm using a
command that I typed in before, and it's
| | 00:14 | calling app.menuList.set, and we're
setting the items property to Brownie and Pizza.
| | 00:21 | When I hit Enter, it updates the model
and the list on the screen updates as well.
| | 00:26 | Let's take a look at how I did it.
| | 00:28 | First I created a new model called MenuList.
| | 00:31 | I set the defaults on line 2.
| | 00:34 | On line 3 I'm setting the items property.
| | 00:37 | This matches up with the name that we
previously used in the ItemsView, so this
| | 00:41 | way we're able to reuse
as much code as possible.
| | 00:44 | Next, I went to index.html and
added a script tag for MenuList.js.
| | 00:50 | After that, I went to app.js.
| | 00:53 | On line 15 I created a new MenuList
model, and then on line 18 I set that
| | 00:59 | model into the MenuView.
| | 01:01 | Finally, I updated the view itself.
| | 01:04 | First, I added an initialize
function on line nine.
| | 01:08 | Then on line 10, I called
the view's listenTo method.
| | 01:12 | The first argument is the model that
we're listening to, the second argument is
| | 01:16 | the change event that we're listening
for, and the third argument is the render
| | 01:19 | function that we're going to
call when the change event occurs.
| | 01:23 | Then finally, on line 14 I'm
rendering the model attributes.
| | 01:27 | When I first tried this,
I left this as this.options.
| | 01:33 | If we go back to the browser and hit
Refresh, you'll notice that the list disappears.
| | 01:38 | This is because we're no
longer setting the view options;
| | 01:41 | we're setting the model, so we
need to render the model attributes.
| | 01:44 | So when you're assigning models to views,
make sure you're pulling data from the
| | 01:49 | correct place and you'll be good to go.
| | Collapse this transcript |
|
|
4. CollectionsOrganizing collections| 00:00 | Models are helpful for
organizing predefined pieces of data.
| | 00:04 | However, there are some situations
where an application will need to work with
| | 00:08 | several models of the same type.
| | 00:10 | While creating a model to hold all of
these models might work, this could get
| | 00:14 | cumbersome very quickly.
| | 00:15 | Instead, Backbone offers collections
as a way of organizing sets of models.
| | 00:21 | I have my server running,
and I'm currently at /items.
| | 00:25 | Rather than showing individual items,
this URL shows the data for every item
| | 00:30 | that's in the system.
| | 00:32 | What I would like to do is have
this data loaded in as a set of models.
| | 00:37 | I can do that with a collection.
| | 00:38 | Let's go to the exercise files.
| | 00:42 | Go to public/js and then collections.
| | 00:46 | There is now menuitems.js.
| | 00:48 | The definition of a collection is very
similar to the definition of a model.
| | 00:53 | On line 3 we have a URL.
| | 00:55 | This is the URL where the data
for the collection can be found.
| | 00:59 | On line 2 however, we're defining the model.
| | 01:03 | You must have a model to define a collection.
| | 01:07 | Every item in the collection will be
filtered through the MenuItem model.
| | 01:12 | On line 1, just like all of the other objects
in Backbone, we're calling the extend method.
| | 01:17 | Let's add this collection to our application.
| | 01:22 | Open up index.html.
| | 01:25 | We need to add the collection here, and
we need to make sure that it gets added
| | 01:30 | after the MenuItem model is
defined; otherwise, we'll get an error.
| | 01:36 | Go to snippets.txt and then copy line 3
into index.html. Copy it onto line 12.
| | 01:47 | Ordering this script after the
MenuItem model ensures that the collection has
| | 01:51 | access to that model.
| | 01:53 | Next, let's add this collection
to the router. Open up app.js.
| | 02:02 | We're going to add this
collection to the initialize function.
| | 02:05 | Copy lines 9 and 10 and
then go to the initialize: function in app.js.
| | 02:12 | Make some room at the top of the function
on line 9 and then paste in those two lines.
| | 02:18 | You'll notice that we're creating the
collection object on line 9 just like
| | 02:22 | we're creating the model object on line 12.
| | 02:26 | And then finally, on line 10, we're
fetching the data from the server.
| | 02:31 | This is similar to the way we're
fetching data from the server on line 36 for
| | 02:35 | the ItemDetails function.
| | 02:38 | Now let's go to the browser.
| | 02:42 | I'm going to open up the
JavaScript Console in Chrome.
| | 02:47 | Now let's type app.menuItems.
This pulls up the collection.
| | 02:56 | Notice we have 12 models in an array.
| | 03:02 | All of the attributes for this model
have been loaded in from the server.
| | 03:06 | We can also fetch a specific model.
| | 03:08 | Type in app.MenuItems and
then call the get method.
| | 03:15 | We can get models by id.
| | 03:20 | To get the model for the garden-salad,
I passed in the garden-salad id, and now
| | 03:25 | we have the garden-salad model.
| | 03:27 | Collections provide a way of
organizing several models of the same type.
| | 03:31 | Once your collection loads data from
the server, models are automatically
| | 03:35 | created and initialized within the collection.
| | 03:38 | The collection object then provides
methods for working with the models it contains.
| | Collapse this transcript |
| Rendering collection data| 00:00 | Rendering collection data is very
similar to rendering model data.
| | 00:04 | The main difference is
that there is an extra step.
| | 00:07 | The models need to be retrieved from
the collection, then rendered individually.
| | 00:11 | At the moment, we have a list of
MenuItems, but this list is hard coded.
| | 00:16 | What we need to do is pass the
collection onto this view and then render the
| | 00:21 | individual models that
are within the collection.
| | 00:24 | So let's go to the
exercise files. Open up app.js.
| | 00:31 | Currently, we're passing an array of items.
| | 00:35 | Let's change this so that we're
passing the collection instead.
| | 00:39 | Open up snippets.txt.
| | 00:42 | Copy line 5. Then go back to app.js
and replace lines 19 through 27 with
| | 00:49 | this new line.
| | 00:52 | So now, instead of having a hard-coded
array, we're passing in the collection.
| | 00:56 | However, we still need to tell the view
to render the collection rather than an
| | 01:00 | array, so let's go to the view.
| | 01:02 | Go to js/views and then menu.js.
| | 01:10 | At the moment, we're cycling
over an array in our template.
| | 01:14 | We need to change this so
that we cycle over a collection.
| | 01:17 | Go back to snippets.txt and then copy line 10.
| | 01:23 | Now replace line 5.
We also need to replace the render function.
| | 01:30 | Copy line 16 from snippets.txt and replace line 10.
| | 01:36 | So now, when the render function is
called, this .collection will be passed into
| | 01:41 | the template function.
| | 01:43 | When the template function receives
the collection, we're going to cycle over
| | 01:47 | the models that are inside the collection.
| | 01:50 | Then inside of each model,
we're going to output attributes.name.
| | 01:55 | Let's try this in the browser now.
| | 01:56 | I already have my server running.
| | 01:58 | If we hit Refresh, you'll
notice that nothing appears.
| | 02:03 | This is because we've loaded the
data but we never listened to the event.
| | 02:07 | This is similar to the problem
that we faced with the model.
| | 02:11 | Collections emit events just like models do.
| | 02:14 | Let's listen to the collection event.
| | 02:17 | Go to line 12 in snippets.txt
and copy the initialize: function.
| | 02:23 | Now let's to menu.js and add this
initialize function to the view.
| | 02:29 | So just like we did for the
model, we're listening to an event.
| | 02:32 | The event we want to listen to is the
Reset event, and we want to listen to the
| | 02:37 | collection that's been assigned to this view.
| | 02:40 | Finally, when that Reset event
does occur, we want to call the render
| | 02:43 | function in this view.
| | 02:44 | So now let's go back to the
web browser and hit Refresh.
| | 02:49 | Now all of the titles are rendering.
| | 02:51 | This is because the data was loaded
from the server and then the collection
| | 02:55 | emitted the Reset event.
| | 02:57 | We listened to the Reset
event and then rendered the view.
| | 03:01 | Collections allow us to load the
data for several models at once.
| | 03:05 | Just like listening for Model events,
we can listen to the Collection events
| | 03:08 | and update the view.
| | Collapse this transcript |
| Sorting collection models| 00:00 | When data is loaded from the server,
it may not necessarily be arranged in
| | 00:04 | any particular order.
| | 00:06 | Collections can automatically sort
incoming data once set into models.
| | 00:11 | So here is our current list.
It's coming from the collection and nothing is in
| | 00:15 | any particular order.
| | 00:17 | Let's sort this alphabetically.
| | 00:19 | Go to the exercise files
and load up the collection.
| | 00:25 | Currently, we're defining the model and the URL.
| | 00:28 | We're going to add another property
to this collection called a comparator.
| | 00:32 | Let's go to the
snippets.txt file and copy it over.
| | 00:38 | Copy line 3 and paste it under line 2.
| | 00:42 | So now we're defining name as the comparator.
| | 00:45 | When the collection has loaded,
it will check the name property of each model
| | 00:50 | and then sort of alphabetically by name.
| | 00:52 | Let's reload the browser and see the result.
| | 00:55 | So now our list is in
ascending alphabetical order.
| | 00:59 | However, let's say we wanted to
order this in descending order.
| | 01:04 | To do that, we'll need to define a function.
| | 01:07 | Go to snippets.txt and copy lines 5 through 11.
| | 01:13 | Then go back to line 2 in
MenuItems.js and paste the function in.
| | 01:19 | This function is a bit more sophisticated.
| | 01:22 | The function takes two models as arguments.
| | 01:25 | This comparator is a
function that starts on line 2.
| | 01:28 | The arguments A and B are two
different models that we're comparing.
| | 01:33 | We're now manually
comparing the model properties.
| | 01:36 | If the name property of A is
alphabetically less than the name property of B,
| | 01:41 | we're returning 1; otherwise,
we're returning -1.
| | 01:45 | This is a standard JavaScript sort function.
| | 01:48 | You can learn more about sort
functions on the Mozilla Developer Network.
| | 01:52 | Now let's refresh our
application to see the sort.
| | 01:55 | Now the titles are sorting in descending order.
| | 01:58 | I'd actually like to set the titles in
ascending order, so I'm going to switch
| | 02:02 | back to the original comparator.
| | 02:05 | Copy line 3 from snippets.txt
and then replace lines 2 through 8.
| | 02:12 | When I go back to the browser and hit
Refresh, everything is now in ascending order.
| | 02:17 | Collections provide a straightforward way
of sorting your models in ascending order.
| | 02:21 | To gain more flexibility in
sorting, define a comparator function.
| | Collapse this transcript |
| Getting models from collections| 00:00 | When a collection has already loaded
individual model data from the server, it's
| | 00:04 | wasteful to fetch the data
by id again from the server.
| | 00:07 | Instead, it's possible to fetch
the model from the collection,
| | 00:10 | then render the data in the view.
| | 00:12 | Let's go to the exercise files
and do this now. Go to app.js.
| | 00:19 | You'll notice that on lines 27 and
28 we're setting the id and then
| | 00:23 | fetching through the model.
| | 00:25 | This is wasteful because we
already have the data in the collection.
| | 00:28 | Let's fetch this data
from the collection instead.
| | 00:31 | Go to snippets.txt and then copy line 5.
| | 00:38 | Then replace lines 27 and 28 with line 5.
| | 00:42 | We're now calling the get
method on the collection.
| | 00:45 | This is loading the model from the
collection that's already been loaded from
| | 00:49 | the server, and then we're just
setting the model in the view.
| | 00:52 | This way we're using the data that
we've already loaded and we're saving a
| | 00:55 | roundtrip to the server.
| | 00:56 | I already have the server running, so I'm
going to load this up in the web browser.
| | 01:02 | When I navigate to Garden
Salad, it loads right up.
| | 01:05 | The same with when I go to Pizza.
| | 01:09 | This data is being loaded from the
collection rather than from the server.
| | 01:13 | We didn't have to do anything to the
view because it just needs a model.
| | 01:17 | The view doesn't care where the model came from;
| | 01:19 | it just cares about what data is in the model.
| | 01:22 | Using a collection helps
avoid roundtrips to the server.
| | 01:25 | By loading all the data through the
collection ahead of time, it's possible to
| | 01:28 | pick out individual models and
then render them through views.
| | Collapse this transcript |
| Adding and removing models| 00:00 | Collections do not necessarily have to
load all or any of their data from the server.
| | 00:05 | Through methods provided in the
collection, it's possible to add or
| | 00:08 | remove models at any time.
| | 00:10 | Let's add some models to this collection now.
| | 00:13 | I'm going to open up the JavaScript
Console in Chrome, so I'm going to go to
| | 00:17 | View > Developer > JavaScript Console.
| | 00:20 | The commands that I want to run are
in the snippets file, so let's go to
| | 00:24 | the exercise files.
| | 00:26 | Open up snippets.txt and then copy line 3.
| | 00:32 | Now first, let's take a look at the
items that are already in the collection.
| | 00:36 | Type in app.menuItems.
| | 00:37 | You'll notice on the line
underneath that the length is set to 12.
| | 00:45 | Let's paste in the
command from the snippets file.
| | 00:48 | Now that we've added this model to the
collection, the length of a collection is 13.
| | 00:53 | However, it does not appear in the HTML.
| | 00:56 | This is because our view is not
listening to the right events.
| | 01:00 | Let's go fix the view.
| | 01:03 | Go to public/js/views, and then menu.js.
| | 01:09 | On line 10, we're currently listening
to the reset event on the collection.
| | 01:13 | However, there are a couple of new
events that we want to add here.
| | 01:17 | Go back to snippets.txt and copy lines 9 and 10.
| | 01:22 | Now, go back to menu.js and add
these lines underneath line 10.
| | 01:29 | We're now listening to two new events:
the add event and the remove event.
| | 01:33 | The collection will emit these events
whenever a model is added or removed
| | 01:37 | from the collection.
| | 01:39 | And then just like reset on line 10,
we're calling this render for both add and remove.
| | 01:45 | Let's go back to the
browser and refresh the page.
| | 01:47 | We still have our list.
| | 01:50 | If we hit up on the console, it will
bring back the last command that we
| | 01:53 | typed. Now hit Enter.
| | 01:55 | You'll notice that not
only the length went up to 13,
| | 01:58 | we now have lemonade in the HTML.
| | 02:01 | This is because we're now listening
for the Add event and re-rendering the
| | 02:05 | view when that occurs.
| | 02:07 | Let's do one more thing.
| | 02:09 | Let's remove lemonade from this list.
| | 02:12 | Type app.menuItems then .remove and
then pass in lemonade in lowercase.
| | 02:21 | Now you'll notice the length went
back down to 12 and lemonade has been
| | 02:24 | removed from the HTML.
| | 02:27 | Models can be added to and
removed from collections at any time.
| | 02:31 | If a collection is assigned to a view,
be sure the view is listening for the add
| | 02:35 | and remove events so that it can be re-rendered.
| | Collapse this transcript |
| Challenge: Selecting items for another collection| 00:00 | For this challenge, make a system where
menu items can be added to a restaurant order.
| | 00:06 | People visiting this site should be
able to click on menu items, then have them
| | 00:10 | added to their order.
| | 00:11 | The first objective is to keep a
separate collection of menu items for the order.
| | 00:16 | Next, make a route where the menu
item is specified. Then a list of
| | 00:20 | ordered items gets displayed.
| | 00:23 | The final objective is to make sure
that the view of ordered items gets updated
| | 00:27 | whenever a new menu item is added.
| | 00:30 | Start this challenge using the exercise files.
| | 00:33 | It should take about ten minutes to complete.
| | 00:36 | In the solution, I'll show how I created
the separate list, as well as a scenario
| | 00:40 | where a specific piece of code is unnecessary.
| | Collapse this transcript |
| Solution: Selecting items for another collection| 00:00 | So, here's my solution to the challenge.
| | 00:02 | All of the menu items now appear as links.
| | 00:06 | When I click on the link for a
menu item, I'm taken to another screen
| | 00:10 | where that item appears.
| | 00:12 | I can repeat the process over and over
again and each item gets added to the list.
| | 00:19 | Let's take a look at the code.
| | 00:22 | First, I createdOrdersView.
| | 00:25 | I added this in the Views folder in orders.js.
| | 00:29 | Next, I created the template.
| | 00:32 | On line 3 I have a header for ordered
items, and then on line 5 I'm displaying
| | 00:37 | the photo for each menu item.
| | 00:40 | Finally, on line 10 we're
rendering every item in the collection.
| | 00:45 | With this file in place, I then went to
line 14 and added this view to index.html.
| | 00:51 | Finally, I updated code in the router.
| | 00:55 | First, on line 13 I
declared a new MenuItems object.
| | 01:00 | Notice that this is the same
MenuItems object that's used on line 10.
| | 01:05 | I'm simply reusing the collection
object and creating a new instance of it.
| | 01:10 | So now we have MenuItems on line
10 and OrderedItems on line 13.
| | 01:16 | Even though we're using the same
collection object, these are two
| | 01:19 | separate collections.
| | 01:21 | This is going to make it possible to
keep track of all of the MenuItems, as well
| | 01:25 | as the MenuItems that have been ordered.
| | 01:28 | With this new collection in place,
I then declared an instance of OrdersView.
| | 01:34 | I passed ordered items as
the collection for OrdersView.
| | 01:38 | With the new collection and view in place,
I then added a new route on line 6.
| | 01:44 | The format of the route starts with
orders and then declares item as a variable.
| | 01:50 | Any route matching this pattern
goes to the new OrderItem function.
| | 01:55 | Let's take a look at OrderItem.
| | 01:55 | OrderItem starts on line 36.
| | 02:01 | The item name passed in through the
route is passed into the function.
| | 02:06 | Given the item name, we then get
that item from the menuItems collection.
| | 02:12 | We store it in a new variable called MenuItem.
| | 02:14 | MenuItem comes back as a model.
| | 02:18 | Since we now have the model, we can
add it to our OrderedItems collection.
| | 02:22 | So on line 38 I'm calling the add
method for the OrderedItems collection.
| | 02:28 | Then finally, on line 40
I'm rendering the OrdersView.
| | 02:32 | Now one thing you may have noticed
in orders.js is that we don't have an
| | 02:36 | initialize function here that's
calling the listenTo method of the view.
| | 02:40 | For instance, in menuitemdetails
we have this listenTo function.
| | 02:48 | We don't need to call the listenTo
function here because in app.js we're always
| | 02:53 | going through orderItem.
| | 02:56 | Since we're always going through the
orderItem function, that means line 40 is
| | 03:00 | always going to execute, which means
the render function of orders.js is
| | 03:06 | always going to be called.
| | 03:07 | So when you're working with Backbone,
always look for opportunities to reuse
| | 03:11 | objects, and also make sure that
unnecessary code does not creep in.
| | Collapse this transcript |
|
|
5. Server-Side IntegrationUnderstanding Representational State Transfer (REST)| 00:00 | Representational State Transfer, also
known as REST, is a software architecture
| | 00:05 | used by the web over HTTP.
| | 00:08 | While REST is not limited to HTTP,
| | 00:10 | Backbone is designed to take
advantage of HTTP's RESTful architecture.
| | 00:15 | Let's take a look at some of
the big concepts behind REST.
| | 00:18 | The first major concept is
that clients connect to servers.
| | 00:22 | Throughout this course, we've been
loading up files in our web browser and our
| | 00:26 | web browser has been acting as the client.
| | 00:30 | A client does not necessarily have to
be a web browser, but we're using a web
| | 00:34 | browser for our application.
| | 00:36 | Another major concept is
that connections are stateless.
| | 00:40 | When you make a connection to a
RESTful service, you make the request, the
| | 00:44 | server fulfills it and then disconnects.
| | 00:47 | There is no state where you
remain connected to the server.
| | 00:51 | Finally, resources are located at specific URLs.
| | 00:55 | On our server, you can go to /items and
get all of the items that are available.
| | 01:00 | You can also get a specific item by
going to /items, another slash, and then
| | 01:05 | the name of the item.
| | 01:07 | Actions on a RESTful service
are carried out using REST verbs.
| | 01:11 | The most common REST verb is GET.
| | 01:13 | Almost anytime you're loading a
file through a web browser
| | 01:16 | it's making a GET request to the server.
| | 01:19 | The web browser is making a
connection to the server, asking for a specific
| | 01:23 | resource, the server is
sending it, and then it disconnects.
| | 01:27 | One of the principles of a GET request
is that no matter how many times you make
| | 01:31 | the GET request, it should
always return the same data.
| | 01:34 | Next, there are POST requests.
| | 01:37 | POST requests are designed to
create a new resource at the given URL.
| | 01:42 | In many existing web applications
this is typically done with a form.
| | 01:46 | Next, there are PUT requests.
| | 01:49 | In contrast to a POST request,
a PUT request will update a resource.
| | 01:54 | And then finally, there are DELETE requests.
| | 01:56 | If you send a DELETE request to a specific URL,
the resource at that URL will be destroyed.
| | 02:02 | REST is designed to standardize
and simplify server interfaces.
| | 02:07 | Backbone has native functionality
using REST verbs in HTTP requests.
| | 02:12 | An understanding of REST makes it
easier to understand what backbone is
| | 02:16 | doing behind the scenes.
| | Collapse this transcript |
| Repurposing forms| 00:00 | First-generation web applications
generally use forms to generate POST
| | 00:04 | requests over HTTP.
| | 00:07 | These forms submit the values
from inputs as request variables.
| | 00:10 | While this is simple to do with
markup, it is difficult to control
| | 00:14 | through JavaScript.
| | 00:15 | Let's write a form but use
it for a different purpose.
| | 00:18 | Let's go to the exercise files.
| | 00:20 | In js/views, there is a
new menuitemform.js file.
| | 00:26 | At the moment, this is a
fairly standard HTML form.
| | 00:30 | We don't have an action on the form,
but we're going to be using this form for
| | 00:34 | a different purpose.
| | 00:37 | Next, we have an events property.
| | 00:40 | The events property allows us to assign
events to DOM elements that are in our view.
| | 00:45 | In this case, on line 26, whenever the
btn-primary class is clicked, we're going
| | 00:52 | to call the setModelData function on line 34.
| | 00:57 | The render function starting on line 29
simply takes the template and renders it.
| | 01:02 | The setModelData function on line 34,
however, is going into the form and
| | 01:07 | scraping the values out of it.
| | 01:09 | This allows us to collect all the values
from the form and set it into the model.
| | 01:14 | Once we have this data in the model,
then we can decide how we want to use it.
| | 01:19 | Let's add this view to our application.
| | 01:22 | Open up index.html.
| | 01:25 | We need to add a script tag here.
| | 01:28 | Go to the snippets file. Copy the script
tag from line 3 and paste it into index.html.
| | 01:39 | Next, we need to update
app.js to use this new view.
| | 01:45 | First, let's start this view
in the initialize function.
| | 01:49 | Copy line 9 from snippets.txt
and paste it on line 20.
| | 01:55 | Line 20 is now creating a new menu item
form object and using a menu item as the model.
| | 02:03 | Finally, we need to update the
itemForm function on line 32.
| | 02:08 | Go back to snippets.txt and copy
the itemForm function, starting on line
| | 02:13 | 12 through line 14.
| | 02:16 | Now, replace the itemForm function on line 32.
| | 02:19 | Instead of the placeholder text,
we're now rendering the menuItemForm.
| | 02:24 | Now, let's go to the browser.
| | 02:26 | I already have the server running.
| | 02:28 | So now, I'm going to click Add Item.
| | 02:32 | I'm going to type in Lemonade as the
name, Beverages as the category, lower-
| | 02:39 | case l lemonade as the URL, and then
no-image.jpg as the image. And now I'm
| | 02:49 | going to click Save.
You'll notice that nothing happened right away.
| | 02:52 | At the moment, we're just collecting the data
from this form and putting it into the model.
| | 02:56 | Let's take a look at this model and
make sure that the data got in there.
| | 03:00 | I'm going to open Chrome's
JavaScript Console; go to
| | 03:03 | View > Developer > JavaScript Console.
| | 03:06 | Now, type in app.menuItemForm.model.
| | 03:16 | Let's inspect this model.
| | 03:18 | Take a look at the attributes object.
| | 03:20 | It has all the data that we entered.
| | 03:23 | By assigning a function to a Form View
click event, we can make a button where
| | 03:27 | we control the behavior.
| | 03:29 | Instead of submitting a form to the
server right away, we can capture the data
| | 03:33 | and then decide what to do with it later.
| | Collapse this transcript |
| Saving data| 00:00 | After extracting data from a form,
you'll generally want to save it back to the server.
| | 00:05 | Let's take the data collected from a
form, save it, then redirect to the
| | 00:10 | single menu item view.
| | 00:12 | We're going to be making changes to the
item form, so let's navigate there now.
| | 00:18 | Also, we're going to be pasting in
code from snippets.txt, so let's load it.
| | 00:27 | First, let's remove the
events property from menuItemForm.
| | 00:32 | Instead, let's add
this.delegateEvents to the render function.
| | 00:37 | Copy everything from lines 5 through 7, then
paste it on line 27 in the render function.
| | 00:44 | Using the delegateEvents function here
ensures that the DOM elements always get
| | 00:48 | the events that they are supposed to.
| | 00:51 | Next, we're going to paste in a save function.
| | 00:55 | Copy everything from lines 9 through
20 and then paste it in on line 33.
| | 01:04 | Whenever btn-primary is clicked,
the save function is going to be called.
| | 01:10 | On line 34, the save function
is calling this.setModelData.
| | 01:16 | setModelData will extract the data
from the form and set it into the model.
| | 01:22 | On line 36, we're calling
the save method of the model.
| | 01:27 | The first argument we're passing in
is the data to be saved to the server.
| | 01:32 | We're passing in the model attributes.
| | 01:34 | These attributes will be encoded as JSON
and sent to the server as a POST request.
| | 01:40 | The second argument is an object.
| | 01:43 | This object has a success property.
| | 01:46 | The success property is set to a function.
| | 01:49 | When this function is called,
the saved model will be passed in.
| | 01:54 | On line 39, we're calling the add
method of the menu items collection.
| | 02:00 | We're passing in the model so that
it can be added to the collection.
| | 02:04 | Finally, on line 40, we're calling
the navigate method of the router.
| | 02:09 | The first argument we're passing in is
the URL that we want to set in the browser.
| | 02:14 | In this case, we're getting the URL
fragment from the model and adding it onto
| | 02:18 | the end of menu items.
| | 02:20 | The second argument we're
passing in is trigger true.
| | 02:24 | This tells the router that we want to execute
the function that is assigned to this route.
| | 02:30 | We have one more change to make.
| | 02:33 | Go back to snippets.txt and copy line 23.
| | 02:40 | Paste this in menu item form.js, on line 50.
| | 02:45 | We're setting the ID to null
whenever we call setModelData.
| | 02:49 | This ensures that if we reuse the form
for another item, it's going to get its own
| | 02:55 | unique ID when it goes to the server.
| | 02:57 | Now, let's save this file
and load the web browser.
| | 03:00 | I already have the server running,
so I'm just going to go there.
| | 03:06 | Let's try adding an item.
| | 03:08 | When I click Save, it takes me to the new item.
| | 03:12 | Let's try adding another one.
| | 03:16 | When I come back to the food list
and hit Refresh, both Iced Tea and
| | 03:21 | Lemonade appear in the list.
| | 03:23 | Once data is stored in an object,
it can be sent back to the server using
| | 03:28 | the model's save method.
| | 03:30 | This method generates a POST
request and encodes the object as JSON.
| | 03:35 | We can define a call back function to
be run when the save is successful, giving
| | 03:39 | us the opportunity to decide how to proceed.
| | Collapse this transcript |
| Deleting data| 00:00 | Sometimes you'll want to
remove data from the server.
| | 00:03 | This is possible through Backbone's
models when the ID for the record is known.
| | 00:07 | Let's provide a delete
function on the single item view.
| | 00:10 | So, let's go to the single item view now.
| | 00:13 | Open menuitemdetails.js.
| | 00:17 | Currently, we're simply
displaying the menu item.
| | 00:20 | We don't have any controls for
deleting the record, so let's add them now.
| | 00:25 | Open up the snippets.txt file.
Copy everything from line 5 to line 7, then go
| | 00:35 | back to menuitemdetails.js.
| | 00:37 | Now, before you paste this in,
be sure that you're at the end of line 7.
| | 00:45 | You'll notice that we're
concatenating a string here.
| | 00:48 | At the end of every line, there's a
plus symbol, except for the last line.
| | 00:53 | On line 8 we're adding a space.
| | 00:56 | Then on line 9 we're adding a button.
| | 00:59 | Users will be able to click
this button to remove the record.
| | 01:02 | However, we need to
associate an event with this button.
| | 01:05 | Let's go back to the
snippets.txt file and grab it.
| | 01:09 | Copy everything from line 10 to
line 12, and then paste on line 18.
| | 01:14 | We're calling the
delegateEvents function of the view.
| | 01:19 | This allows us to
associate an event with a function.
| | 01:23 | In this case, whenever btn-dangerous
clicked, the deleteItem function of
| | 01:28 | this view will be run.
| | 01:30 | This delegateEvents function on
line 18 will be run everytime the
| | 01:34 | render function runs.
| | 01:36 | This will ensure that, no matter how
many times the markup gets rendered, we'll
| | 01:40 | always have the event we need.
| | 01:43 | Let's go back to snippets.txt and get the
deleteItem function that's referenced here.
| | 01:50 | Copy everything from line 14 to
line 23. Then paste it on line 16.
| | 01:58 | On line 17, we're calling the
destroy method of the model.
| | 02:03 | Since we've already loaded this model
with an ID, backbone will know what URL to
| | 02:08 | send the delete request to.
| | 02:09 | We're passing one argument into destroy.
| | 02:14 | It starts on line 18 and ends
on line 23. It's an object.
| | 02:19 | This object has a property named success.
| | 02:22 | Starting on line 19,
we're defining a callback function.
| | 02:26 | When the delete request finishes on
the server, the model will be passed into
| | 02:30 | this callback function.
| | 02:32 | Then on line 20, we're removing
this model from the collection.
| | 02:36 | We're getting the ID from the model so we
can tell the collection which model to remove.
| | 02:42 | Finally, on line 21, we're telling
the router to go back to the main page.
| | 02:47 | We're also passing in trigger true.
| | 02:51 | This tells the router to execute the
function that's located at this route.
| | 02:56 | Let's save this file and go to the browser.
| | 02:58 | I already have the server running,
so I'm just going to load the site.
| | 03:03 | First, let's go to Garden Salad.
| | 03:06 | Click the Delete button.
| | 03:07 | You'll notice that we got redirected
back to the main list and that Garden Salad
| | 03:12 | is no longer on this list.
| | 03:14 | Let's delete another record.
| | 03:17 | At the end of the URL, add menu
items, and let's go to Cheeseburger.
| | 03:27 | Now, let's delete this from the menu as well.
| | 03:30 | You'll notice that we got redirected
back to the list and Cheeseburger is no
| | 03:34 | longer on that list.
| | 03:35 | Backbone can generate delete requests via the
model's destroy method when an ID is set.
| | 03:41 | A callback function can be defined for
when a delete is successful, allowing us
| | 03:45 | to redirect the user appropriately.
| | Collapse this transcript |
|
|
6. Performance TuningCompiling templates| 00:00 | Markup is easiest to read
when it's in a file by itself.
| | 00:04 | Instead of adding markup as
concatenated strings in views, Handlebars makes it
| | 00:08 | possible for templates to be precompiled.
| | 00:10 | Precompiling templates allows us
to use a reduced subset of the
| | 00:14 | Handlebars library.
| | 00:16 | Let's download this reduced subset now.
| | 00:18 | On the Handlebars home page,
there's a large button for Download.
| | 00:22 | Underneath this button is a
link to download the runtime.
| | 00:26 | We just want the runtime now.
| | 00:28 | I'm now going to save
this runtime to the desktop.
| | 00:35 | Now that we have the runtime,
let's include it in our project.
| | 00:38 | Move Handlebars runtime.js to jslib.
| | 00:50 | Now that we have it here, let's replace
the script tag to only use the runtime.
| | 00:55 | I have index.html open, and now
I'm going to open snippets.txt.
| | 01:02 | Copy line 2 from snippets.txt.
Then in index.html, replace line 9.
| | 01:08 | So now we're reloading handlebars.runtime.js.
| | 01:13 | Next, let's take a look
at compiling our templates.
| | 01:17 | Go to terminal and
navigate to the exercise files.
| | 01:21 | I'm going to type in cd, space, capital
DE for desktop, then tab over, capital EX,
| | 01:29 | for exercise files, then 06/01/start.
| | 01:37 | I want to go to the public folder, and
there's a subfolder that's been added.
| | 01:42 | If you notice here, in the public folder
there's a templates folder that's been added.
| | 01:48 | There are now three files here for
the form, the details, and the menu.
| | 01:52 | Let's open one of these files now.
| | 01:56 | You may need to specify an application
to use with the .handlebars extension.
| | 02:02 | I'm going to open it with TextMate.
| | 02:04 | This file has all the
markup for the details view.
| | 02:08 | We're still using the Handlebar syntax,
but we're not concatenating any strings.
| | 02:12 | This is much easier to read and maintain.
| | 02:14 | Now, let's compile this
template, along with the other two.
| | 02:17 | Change directory into public/templates.
| | 02:24 | We're now going to install a command-line
tool to help us compile these templates.
| | 02:28 | It's available via node package manager.
| | 02:31 | You can learn more about node package
manager in Node.js First Look on the
| | 02:35 | lynda.com online training library.
| | 02:38 | To install this tool, I'm going to
type in sudo npm install -g handlebars.
| | 02:52 | It may not be necessary for you to use
sudo on your machine, but it is on mine.
| | 02:57 | Sudo will prompt you for the password.
| | 03:03 | We now have the Handlebars command installed.
| | 03:06 | We can use it by typing in GHandlebars.
| | 03:09 | Typing it in and hitting Enter
will simply bring up a Help screen.
| | 03:13 | To use it, let's pass in
the names of our templates.
| | 03:16 | We have form.handlebars,
details.handlebars, and menu.handlebars.
| | 03:26 | We want to take all three of these
templates and compile them into one file.
| | 03:31 | So, we're going to use the -f flag and
then we're going to specify the name of
| | 03:35 | the file we want to compile to.
| | 03:37 | Let's compile these templates to templates.js.
| | 03:41 | Let's have a look at what got generated.
| | 03:45 | There is now a templates.js
file in our Templates folder.
| | 03:49 | You'll notice that the
code is not very readable.
| | 03:52 | However, it's very efficient.
| | 03:54 | It has all of the markup that we
included in our templates, and it's running the
| | 03:59 | Handlebars code through it.
| | 04:02 | Now, let's add this
templates file to our application.
| | 04:04 | Go back to snippets.txt and copy line 4.
| | 04:10 | Paste this tag on line 10.
| | 04:13 | Always make sure that the templates.js
file you generate is ordered after the
| | 04:18 | Handlebars runtime.
| | 04:22 | Finally, we need to go back and adjust
our views to use the compiled templates
| | 04:26 | rather than the concatenated strings.
| | 04:28 | Go to js and views and
first, let's open menu.js.
| | 04:35 | Remove everything from line 3 to line 8,
and then we're going to replace line 10.
| | 04:46 | Copy line 13 from
snippets.txt and paste it on line 10.
| | 04:50 | You'll notice we have handlebars.templates.menu.
| | 04:56 | When you compile your templates,
it takes the name of the template file name and
| | 05:00 | adds it as a property of the templates object.
| | 05:03 | This becomes a method where you can pass in the
data that you normally would in the handlebars.
| | 05:09 | We're going to use the same
approach for the other two views.
| | 05:14 | Open up menuitemdetails.js, then
remove everything from line 2 to line 10,
| | 05:21 | then replace line 20.
| | 05:23 | Go to snippets.txt and copy
line 7 and then replace line 20.
| | 05:32 | Notice again that the name of the
template is available as a property of the
| | 05:36 | templates object, and now let's adjust the form.
| | 05:44 | Remove everything from line 2 to line
23, then go to snippets.txt and copy line
| | 05:50 | 10, then replace line 5.
| | 05:55 | Save this file and now we're
ready to load this site in our browser.
| | 05:58 | I already have the server running,
so I'm just going to go there.
| | 06:03 | You'll notice that our list and our
form and our single item view are all
| | 06:08 | rendering just as before.
| | 06:11 | Precompiling your templates reduces not
only the download size for the browser
| | 06:15 | but also reduces the
rendering time for the view.
| | 06:18 | Also, keeping your view markup in
separate files makes it easier to read.
| | 06:22 | Precompile your templates whenever possible.
| | Collapse this transcript |
| Bootstrapping data| 00:00 | Whenever practically possible,
reducing the number of requests to the server
| | 00:04 | will improve the
performance of your application.
| | 00:07 | Since we're going to be loading an
HTML file anyway, why not embed the
| | 00:11 | collection data directly into this file?
| | 00:14 | This practice is known as bootstrapping.
| | 00:15 | We're going to bootstrap of collection data now.
| | 00:19 | In previous videos, I have the server
already running, but in this one I don't
| | 00:24 | have it running yet.
| | 00:26 | We're going to be making a small
change to the server in this video, and then
| | 00:29 | we'll start it later.
| | 00:30 | First, let's go to the exercise files.
| | 00:33 | At the moment we have index.html here,
and this gets loaded whenever we go to
| | 00:38 | local host at port 3000.
| | 00:39 | What we want to happen instead is we
want to use the templating engine in the
| | 00:44 | Express framework that's
being used by the Node server.
| | 00:48 | Express has a naming convention where
it uses a folder name to views to hold
| | 00:53 | mark up that it delivers.
| | 00:55 | Let's add that folder now.
| | 01:00 | Next, let's move index.html into views.
| | 01:06 | We need to rename this file.
| | 01:07 | Unfortunately, if we try to do it in
Finder here on the Mac, it won't do it correctly.
| | 01:13 | So let's go to the command line.
| | 01:15 | We're going to change
directory to the exercise files.
| | 01:19 | Type in cd, space, and then capital D,
and then E and then tab for Desktop,
| | 01:25 | capital E, and then X, and then
tab for Exercise Files, then 06/02.
| | 01:32 | Follow that by start and views.
| | 01:37 | I'm now going to move the file to rename it.
| | 01:39 | So type in mv, and space, then index.
html, and then another space, and then we're
| | 01:47 | going to name the file index.hbs.
This is going to allow us to use Handlebar
| | 01:54 | syntax on the server side
rather than in the browser.
| | 01:59 | Let's open this file now.
| | 02:02 | You may need to choose an
application to open it with.
| | 02:06 | I'm going to choose TextMate.
| | 02:09 | At the moment, we just
have the existing index file.
| | 02:12 | What we need to do now is add a
placeholder for the collection data.
| | 02:17 | Let's go to snippets.txt.
| | 02:23 | Copy lines 3 through 5. We're going to
add this snippet after app.js is loaded.
| | 02:29 | Go to line 17 and paste in the script.
| | 02:32 | You'll notice on line 18
we're calling app.menuItems.reset.
| | 02:38 | What this is doing is telling the
collection to use the data that we're passing in.
| | 02:44 | Also notice that we're using
three sets of curly braces.
| | 02:48 | This tells Mustache to not escape the data.
| | 02:51 | We don't want to apply HTML escaping
to this data because the JSON that we're
| | 02:56 | outputting is going to be JavaScript.
| | 02:59 | Now let's make an adjustment to the server.
| | 03:04 | Open server.js and then in snippets.txt,
copy lines 9 through 11. Then go back to
| | 03:12 | server.js and paste on line 8.
| | 03:17 | You'll notice that in this case we're
loading index.hbs, and then for the data
| | 03:22 | variable we're passing in a
JSON string of all the items.
| | 03:28 | Finally, let's make one more adjustment.
| | 03:31 | Lets go to app.js in the front end.
| | 03:36 | Scroll up to line 10.
| | 03:38 | We don't have a need to call the Fetch
method on menuItems because we're calling
| | 03:42 | a reset in index.hbs.
| | 03:45 | This is going to save us
a request to the server.
| | 03:48 | So let's remove this line
now. Now save the file.
| | 03:51 | Let's go back to the
command line to start the server.
| | 03:54 | We're going to change directory.
| | 03:57 | Type in cd, space, and then
period, period to go up one level.
| | 04:04 | Now type in node, space, server.js.
| | 04:09 | It says the server is ready at port 3000.
| | 04:11 | Now let's load the site in our browser.
| | 04:13 | You'll notice that all the items that
were there before are now here again.
| | 04:18 | We eliminated an HTTP request we no
longer need because that data is now being
| | 04:23 | directly embedded in our HTML file.
| | 04:26 | Let's view the source.
| | 04:27 | You'll notice that app.menuItems.
reset is what we entered into the index.hbs file.
| | 04:40 | Then the server filled our
placeholder with all of the collection data.
| | 04:45 | Bootstrapping your data is a good
way of improving your application's
| | 04:48 | performance, especially when there's an
opportunity to generate the HTML file.
| | 04:53 | Be sure that the JSON string does not
get HTML escaped. Then add the call to the
| | 04:59 | collections Reset method
after it's been initialized.
| | Collapse this transcript |
|
|
ConclusionExploring Backbone-based tools| 00:00 | One of Backbone's benefits is that all
of the code is extensible and reusable.
| | 00:05 | Several frameworks extend Backbones
functionality with their own set of tools,
| | 00:09 | making it easier to get projects started.
| | 00:13 | First, let's take a look at marionettejs.
| | 00:16 | Marionette is available at marionettejs.com.
| | 00:19 | Marionette.js has the concept of modules.
| | 00:23 | Modules are used so you can
group related views and models and
| | 00:27 | collections together.
| | 00:29 | This way you can start them up when
you're ready to use them and then close
| | 00:32 | them out as a group.
| | 00:34 | Next, Marionette allows you to nest views.
| | 00:38 | In our application we had a list of menu
items that were each represented by a list item.
| | 00:44 | You can have one view for the list as a
whole with several other views for the
| | 00:48 | individual list items.
| | 00:50 | Finally, marionette.js
provides for memory management.
| | 00:54 | When we were building the application
earlier, we were trying to reuse the same
| | 00:58 | model and view objects over and over again.
| | 01:01 | Marionette has some tools
that makes this simpler.
| | 01:05 | Next, let's have a look at Thorax.
| | 01:08 | Thorax is available at thoraxjs.org.
| | 01:12 | One advantage with Thorax is
that Handlebars is included.
| | 01:15 | There's also a helper functionality
built into Thorax that makes it easier to
| | 01:19 | work with Handlebars.
| | 01:21 | Thorax also has easy form handling.
| | 01:24 | Earlier on, we wrote some
code to get values from a form.
| | 01:28 | We had to write some jQuery to get
the values of each individual input.
| | 01:33 | Thorax has functionality where you
can do this with one line of code.
| | 01:37 | And finally, Thorax has a seed project
you can use to start your own project.
| | 01:42 | This has everything laid out and
ready to go, so you can start coding.
| | 01:46 | Marionette and Thorax are just two
examples of frameworks that are built on Backbone.
| | 01:52 | Both of them provide functionality
beyond what Backbone does natively.
| | 01:56 | While you lose some of the flexibility
and simplicity Backbone provides, you
| | 02:01 | also gain helpful tools for
building large applications.
| | Collapse this transcript |
| Finding Backbone resources| 00:00 | Once you have an idea of the
functionality Backbone can provide for you, there
| | 00:05 | are many online resources
you can use to dig deeper.
| | 00:08 | The first one is backbonejs.org.
| | 00:12 | Backbonejs.org has all the
documentation that you need for Backbone.
| | 00:18 | If you scroll down to the bottom,
there are examples of Backbone in action.
| | 00:27 | Next, let's have a look at underscorejs.
| | 00:29 | Underscore is a library that
Backbone is built on top of.
| | 00:33 | All of the documentation for
underscorejs is available at underscorejs.org.
| | 00:40 | Backbone is developed using GitHub.
| | 00:43 | You can follow the progress
of Backbone on its GitHub page.
| | 00:47 | And then finally, backbonejs has a Google group.
| | 00:51 | Members of the Backbone community use this Google
group to talk to each other and to learn more.
| | 00:56 | Backbone is a growing open source project.
| | 00:59 | Use these sites to track the
development of Backbone and to learn more about
| | 01:03 | how it can serve your needs.
| | Collapse this transcript |
|
|