Heads up! To view this whole video, sign in with your Courses Plus account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
In this video we learn about Backbone Collections and how they are used to manage sets of data in our application. here.
This video doesn't have any notes.
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
[?music?]
0:00
[Backbone Collections]
0:02
[Jim Hoskins] So now we have our form in a state
0:06
where it will actually take all the information from the fields and save it into a New Note.
0:09
However, when we do this and we submit it:
0:13
Text Body
0:18
--even though it's saving, it's not quite having the behavior we want.
0:20
When we save it, it seems to submit and has that sort of slide forward form.
0:23
But you remember, the way we actually brought it up was a dialog,
0:28
so how we actually like it to complete
0:32
is to simply puff away much like that.
0:35
So what we need to do is go into our View,
0:40
and here we are inside of our new Views form.
0:43
So after we create the note, what we want to do is two things.
0:47
First we want to tell the browser that we don't want it to submit like a normal form,
0:52
and we can do that by using the event object that's passed
0:56
into our createNote handler and telling it to prevent default,
0:59
which will stop a normal form load.
1:03
The second is we want to stop the propagation of this submit event
1:05
and that's because jQuery Mobile also does some magic
1:09
whenever it sees forms in order to make our app run like a typical iPhone or IOS application.
1:12
That means it intercepts a form submission,
1:18
does some AJAX, and then moves into another page,
1:21
and we don't want jQuery Mobile doing that, either.
1:24
So what we're going to do is we're going to call e.preventDefault();
1:27
and this will stop our browser from submitting the form like normal.
1:30
The second thing we want to do on that event is call e.stopPropagation();
1:34
which will stop jQuery Mobile from intercepting that event
1:38
and doing its AJAX magic.
1:42
Now, in the event handlers, the equivalent of calling e.preventDefault();
1:44
and e.stopPropagation(); would be to simply return false from this handler function,
1:48
but I prefer to do it more explicitly like this.
1:53
So now we've prevented the browser from submitting the form
1:57
and we've prevented jQuery from handling the form and doing its normal animation.
2:00
Now, the last thing we want to do is to close the dialog in its normal way.
2:05
We also want to reset the form fields because we don't want
2:10
the input from the previous one to show up when we start adding a new note.
2:12
So the way that we can close the dialog--
2:16
let me just move this up the screen a little bit--
2:20
and to close the dialog, all we need to do is call this piece of code right here,
2:23
and what this does is it's a jQuery call
2:28
and it uses a selector here
2:31
and it uses the .ui-dialog to capture any dialog that's open;
2:33
in our case, our new form.
2:37
And then, we can call the dialog plugin and pass it the method "close")
2:40
and that's a way you can close whatever open dialog there is
2:45
from anywhere in your application.
2:49
Finally, we want to reset it, and I'm going to delegate this out to a new method,
2:51
so we'll call this.reset();
2:54
and let's go ahead and create our reset function.
2:58
reset: function(){
3:01
Now, one way we could handle this reset is to use the built-in reset functionality
3:07
built into forms, but later on, we're going to run into a problem
3:11
where the toggle switch doesn't recognize that a select field
3:15
has changed state because of a reset request from the browser
3:19
so we're going to do it manually,
3:23
and I'm just going to paste in this code.
3:27
What this code is going to do is it's going to grab all of the inputs and text areas
3:29
from within this view and just set the value to the empty string,
3:33
which will essentially reset it.
3:38
So if we save this out and we refresh our page,
3:40
let's create a new one and we'll just call this Next Test
3:43
and Some Text Here
3:49
and we save it out--cool.
3:51
We got the dialog to pop away just like it popped up.
3:55
If we bring up the New Note, it's all cleared out and ready to go
3:58
for the next one, so it looks like we got our New Note dialog all set up.
4:02
Our next step is we want to make the page that this would link to functional,
4:07
which would display a list of all of the notes.
4:11
So what we're going to do is we're going to start in our HTML file
4:14
and create a new page under the name All.
4:17
So if we go back to our HTML page,
4:23
first, I'm going to collapse our new page here,
4:28
and if we look here, we see that we link to All,
4:31
so what we're going to do is create a new page
4:35
with the id of "#all" that will have a list of all of our notes.
4:37
So I'm also going to just spin that up.
4:41
We'll go ahead and start our next page
4:46
and we'll call this List of Notes.
4:49
All right. I'll paste this in, cut some stuff out.
5:01
Cool. So I'm just going to paste this in and let's just go over it.
5:10
It's a lot like the pages we've created before.
5:14
We start with the id of "all" and we give it a data-role of "page">.
5:17
Then here, we're defining our header, so it has a data-role of "header"
5:22
and its title is All Notes.
5:25
Here we've added a Back button,
5:28
and this is a button that jQuery Mobile adds by default
5:31
when we are navigating around our pages,
5:34
but the reason I add one in manually is because if somebody bookmarks this page
5:36
and loads it fresh and jQuery mobile doesn't know what the previous page would have been,
5:40
this offers us a default Back button which will take us home in all cases.
5:46
So we just did a normal button with the data-role of "button".
5:50
We have our data-icon of arrow left "arrow-l"
5:56
and then, we added this data-rel="back">
5:59
and this tells jQuery Mobile that when we can, just have it act like a Back button
6:02
and just take them back to wherever it was.
6:07
However, if it can't use the normal Back functionality,
6:09
it will take you to Home, which will work for if we load this page from a bookmark.
6:12
So that's our header, and then we have our div for our content.
6:18
Now, what I'm going to do here is just paste in an unordered list
6:24
with the data role of "listview"
6:28
which is what we saw on our homepage,
6:30
but you'll notice I am not having it with data inset true.
6:33
I want this to be an edge-to-edge list because this page is going to be nothing
6:36
but this single list of notes
6:40
and I've given it an id of "all notes">.
6:42
Now what we're going to do is we're going to fill in this list dynamically using Backbone.
6:46
Each list item in this list view
6:52
is actually going to be represented by its own instance of a View
6:55
that we're going to write, and that view is going to be called a NoteList item.
6:58
Besides each of those individual Views inside of it,
7:03
we're also going to create a View that represents this list,
7:06
and that will manage things like adding new items to the list
7:09
or just populating the list by itself.
7:14
So we're going to have two different Views:
7:16
one represents the entire list and will watch for a collection of notes
7:18
and add the list items in and each of those list items itself will be a View
7:24
and those will be concerned with changes to the Title or any other content
7:30
for that particular list item.
7:34
So now, before we start defining our Views, we need to introduce a new concept
7:37
which is very closely related to our model,
7:42
and that's the idea of a collection.
7:44
So while a model represents a single note,
7:51
a collection represents a list of multiple models or multiple notes.
7:55
In Backbone, collections are used for keeping lists of things
7:59
so they can be updated on the server.
8:03
It can be a little bit tricky to understand where to use collections,
8:05
but basically, we want a collection because we're going to be showing a list
8:08
and having that collection object will give our list View
8:13
something to look at and observe
8:17
and the collection can notify our View when a new note is added to the list
8:18
or the new note is removed or anything like that.
8:24
So the collection sits between our database or our localStorage
8:28
as an abstraction of that.
8:32
Our collections are going to be pretty simple--
8:34
they're just going to represent the entire contents of our database or localStorage.
8:36
So we don't interact directly with the localStorage; instead we use these collections
8:42
and they will watch our localStorage and notify us of any changes.
8:47
So I'm going to define a collection here, and we'll call it a NoteList.
8:57
var NoteList
9:02
and we're going to inherit from the Backbone collection class,
9:05
so we'll say Backbone.Collection.extend({.
9:08
What we're going to do here is add some properties and methods
9:16
to customize how our collection works for our notes class.
9:19
The first built-in property we want to specify
9:22
is the model property, and this will tell Backbone
9:25
what type of model we're dealing with.
9:28
In our case, we're dealing with the Note.
9:30
The next thing we want to do is tell it that it's going to utilize localStorage as its data source.
9:34
In order to do that, we just add the localStorage property
9:39
and tell it to use App.stores.notes, which we can remember
9:43
we defined up here, right at the beginning of our code.
9:48
This is exactly the same as our note model here,
9:51
which means that they're using the same database or localStorage database
9:54
when we save a model directly as well as when we try to retrieve a list of models
9:59
from our localStorage.
10:04
So this tells our collection that it's watching localStorage
10:06
and let's add an initializer here.
10:09
initialize: function (){
10:11
and we're actually going to have to make a change to our localStorage code.
10:22
See, the type of application we're creating isn't really the typical use for Backbone.
10:25
A collection is really used to sort of abstract away an endpoint on a web service,
10:30
and the way we're using it now
10:35
is we are going to have multiple collections:
10:39
one collection for sorting by name
10:41
and one location for sorting by geolocation or how close that note is to your current location
10:44
and the way we're saving notes themselves is not actually saving them through a collection
10:50
but just saving them directly, which will store them into localStorage.
10:55
So when we create a New Note and save it into localStorage,
10:58
the collections that we also have hooked up to that same data store
11:02
are not going to be notified of that change.
11:06
So the way we can handle this is we can modify the localStorage code
11:09
to send out an event every time that the data is updated.
11:14
Any collection that's set up to use that data store as its database
11:19
can be set up to watch for that update event and then handle itself accordingly.
11:24
So what we're actually going to do is we're going to open up the Backbone.localStorage.js.
11:30
Now, even though this isn't a library that we wrote,
11:36
unfortunately, I couldn't find an elegant way to get around having to modify
11:38
this library code, so it's worth taking a look.
11:43
It's not too difficult to understand; there's some things here about generating random numbers
11:47
to manage our id, but basically, we're just creating a store.
11:54
It will load the load the store from localStorage.
11:58
And then there's these functions here which are called behind the scene in Backbone
12:01
whenever we save an object.
12:05
So for instance, this save method is just going to call the localStorage.setItem
12:07
and then just sort of stringify its current internal memory,
12:12
and later on, when we restore from it, it'll read from localStorage and deserialize it.
12:18
Now, you can see that create also implicitly calls save,
12:24
update also calls save,
12:28
and destroy calls save,
12:32
so any time our data actually changes, the save function is invoked.
12:34
So if we're going to notify the outside world of any changes to our database,
12:39
we're definitely going to want to do it from inside of this save function.
12:44
Backbone has another class that's really useful to use
12:50
in any situation, and it's called Events. documentcloud.github.com/backbone/#events
12:53
What we can do is we can extend any object or any class
12:58
with Backbone.events, and what that will add is three methods:
13:01
object.bind, which will allow us to watch for a certain type of event
13:04
to be broadcast from this particular object;
13:09
similarly, an unbind method, which will remove any listener from it,
13:13
as well as the trigger.
13:16
Trigger and bind work together, so the object will trigger to create a new event.
13:18
For instance, we can trigger an update event
13:22
and then other parts of our code can bind to that update event
13:25
and every time that save method is called, we can hook our own code into there
13:29
to update, for instance, our collections.
13:34
In order to do that, we need to make sure that store class extends from Backbone.events
13:37
and if we go look at our code,
13:43
we can see that we're already extending Store.prototype with these methods.
13:46
So what we can do is the extend method can take in multiple objects
13:50
that will be all extended to Store.prototype.
13:54
So we'll just type in Backbone.Events, (comma)
13:57
so now our store will also extend from Events
14:03
as well as this custom code, and we can now use bind and trigger on this object.
14:06
So in our save function, when we update our localStorage database
14:15
with the new information, all I'm going to do is call this.trigger
14:19
since now this has a trigger method,
14:24
and let's call our event ("update")
14:27
which will just say that the data inside of our localStorage data store
14:29
has been updated.
14:33
So now, any time our localStorage updates, it's going to broadcast an event
14:36
called update, so inside of our initializer, what we're going to do
14:41
is we're going to grab this.localStorage, which is our data store right here,
14:45
and we're going to use the bind() method and look for the ("update") event.
14:51
So every time our localStorage is updated,
14:57
this function(){ that we're going to define here will be executed.
15:00
What we want to do when the localStorage or the underlying data store is updated
15:05
is to tell this collection to fetch, and what fetch does in a Backbone application
15:10
is it goes to its data source, whether it's localStorage or a remote web service
15:16
and gets that full collection from it.
15:21
So in our case, calling fetch will look at the localStorage and just retrieve
15:24
all of the items in that particular store.
15:28
So all we need to do is call this.fetch; however,
15:31
because we're using a callback function, what this refers to on this particular line
15:34
is no longer our collection, but instead whatever this particular function is bound to.
15:39
So in order to get around that, what we're going to do is set a variable called collection
15:46
var collection and set it = this;
15:51
So now, the current value of this at this scope
15:54
is now assigned to a variable called collection
15:56
and then in here, we can call collection.fetch();.
16:00
which would basically be like calling this.fetch.
16:04
Now, when fetch is called, besides just getting the data from the remote source,
16:12
it'll also set off a bunch of different events that other parts of our code will listen to
16:16
and that change will cascade all the way down to our views
16:20
saying that things have changed.
16:24
So we'll see how this comes into play when we write our next piece of code.
16:26
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up