Start a free Courses trial
to watch this video
In this video we setup the skeleton for our application and learn how to define and save Backbone models into the storage database. Get the Code Example.
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 [Introduction to Backbone and Models] 0:02 [Jim Hoskins] In this Master Class, we're going to continue building our HTML5 0:06 mobile note-taking application. 0:11 This is the second Master Class in our series. 0:13 In the first Master Class, we outlined our project requirements. 0:15 http://membership.thinkvitamin.com/library/html5-mobile-web-applications 0:19 We determined that it needed to be optimized for mobile, use localStorage for the database, 0:22 and be location-aware. 0:25 We determined that we would use jQuery Mobile for handling the user interface 0:26 and we would use Backbone.js to manage the data. 0:30 We set up our project and created a basic homepage 0:34 and note form for our application using the built-in functionality of jQuery Mobile. 0:37 In this Master Class, we will write the JavaScript that will handle 0:42 saving our notes in the database and updating our user interface whenever a note changes. 0:45 [?music?] 0:51 [HTML5 Mobile Development with Jim Hoskins] 0:55 [?music?] 1:00 So now we've used jQuery Mobile to prototype the look and feel of our application. 1:02 We've created a homepage and a New Note form, 1:06 but now we actually want to get down to the business of capturing the Note form, 1:10 saving it to a database, and ultimately redisplaying it to the user 1:14 in these different lists here. 1:18 So now, we actually have to start building the logic of our application, 1:20 and we're going to be doing that in our code in this application.js file. 1:24 Now, there's a lot of different ways we could organize our code, 1:29 and right now, we're going to stick with having it all in our application.js file. 1:32 But later on, we can break it out in order to organize our code 1:36 since there's actually quite a bit of it. 1:40 Now, just so you remember, if we look in our index.html, 1:43 our application.js is loaded as the last thing in our application, 1:46 which means we have access to backbone, the backbone localStorage, 1:50 setup, underscore.js, as well as jQuery. 1:54 There's not a whole lot in jQuery Mobile we need right now, 1:58 but we want to make sure our application is loaded last so all of our prerequisites 2:00 and utility libraries are available to us. 2:05 Now, there are a lot of different ways we could organize this, 2:10 but what I'm going to do is I'm going to write all of our code 2:13 in a self-executing private function, 2:15 and I'm going to return the application object from that. 2:18 That means we can create various local variables 2:22 within the scope of our application code that won't leak out 2:25 and interfere with any other code. 2:29 So ultimately, I want a NotesApp variable 2:31 that is available at the global scope, 2:36 and everything is going to be on that object. 2:38 So I'm going assign that to a function that's going to execute, 2:42 so what we return from this anonymous function will be assigned to the NotesApp, 2:48 and that's going to be our application object. 2:52 So what I'm going to do is inside of the scope of this function 2:55 where all of our code will be, I'm first going to create an App object. 2:58 This will be sort of an organizing object that ultimately is returned, 3:02 but will also serve as a way to organize the models, views, collections, 3:06 and other pieces of information that need to be accessed by all of the application logic. 3:12 And let me fix that typo--and we'll do it that way-- 3:18 and there are going to be various objects within this. 3:22 We need to make sure at the end of our code to return App; 3:26 that way the NotesApp will take on the ultimate value of our App object in here. 3:30 Now, one thing that we want to use is to be able to have our localStorage data store, 3:37 and if we open up the Backbone localStorage file, 3:42 we can see that code that is used. 3:46 We don't really need to worry about it. 3:49 But the way we're going to use it is we're going to instantiate one of these Store objects 3:51 with a specific name to hold this type of object. 3:56 For instance, we can create a store to hold all of our Note objects 4:00 and if we had other things like locations or users, 4:04 it would create separate store objects to maintain those separate collections. 4:08 Now, we don't need to worry about the particular code in here. 4:12 We will have to probably modify it a little bit later, but right now, all we need to do 4:15 is instantiate a Store object, and then we'll be able to use that in our code 4:19 as the localStorage in which to store all of our data. 4:24 So I want to organize our Stores in our App object, 4:31 so I'm going to create a property of our App object called stores: 4:34 and I'm just going to make this an empty object so we can assign to it later. 4:39 Now, the first thing I want to do in our app is to initialize our store for Notes 4:42 and that's because we want to make sure our localStorage is set up 4:47 and ready to use any time within this application. 4:50 So what I'm going to do is simply paste in this code here 4:55 and I'm saying App.stores, and I'm creating a new Store called ("notes")' 4:57 and I'm just going to instantiate a new Store object for ("notes"); 5:02 We'll be using this later and specifying when we want to use this particular store 5:05 as we define our code later, 5:11 but now we know we have this available to us in App.stores.notes. 5:13 So you may be familiar with the model view controller paradigm, 5:18 and that is different parts of our application or different parts of our code 5:21 manage different parts of our actual application 5:25 and the model is probably the most core concept. 5:28 A model represents a particular object in our application. 5:31 Now, there's really only one sort of object in our application 5:34 and that would be a Note; 5:37 so a Note is something that we could have multiple of. 5:39 We're going to be creating them, modifying them, viewing them, 5:42 and we want to be able to manage all that through a specific API 5:45 so we want to be able to instantiate a note object 5:49 and have that be able to be saved from session to session, 5:52 so a Backbone model is ideal for managing that type of interaction. 5:57 You can actually look at the Backbone API 6:01 documentcloud.github.com/backbone/ 6:03 to find out all of the things the model can do. 6:05 So models allow us to instantiate a note, for instance, 6:07 and it can have properties and it can be saved. 6:10 For instance, we can tell it we want it to save to the localStorage data store, 6:14 and when we call a save method on a model, 6:18 it'll automatically save into that particular data store. 6:21 Another cool feature is the way attributes are handled. 6:26 Instead of using normal attributes like saying note.title = some value, 6:29 instead, we use the get and set methods on our model 6:34 to actually get and set those properties. 6:37 Now, while this makes it a little more difficult to code, 6:40 it has the added benefit of a model being able to tell whenever a property changes. 6:43 And whenever a property does change, it will actually send out an event notification 6:48 to anybody listening, and this is great because if we change a property of one of our Notes, 6:53 various things need to be updated, like the page that represents that note 6:59 needs to have its title updated, or a list view where we list all the Notes, 7:03 needs to have its title updated. 7:07 So being able to listen to changes is an extremely valuable feature 7:09 that's made available in the Backbone model. 7:13 So let's define a model called Note. 7:17 So to do this, let's create var Note. We use a capital "N" to notify that it's a class. 7:23 What we're going to do is we're going to extend Backbone.Model, 7:31 and to do that, we do = Backbone.Model 7:34 and the Backbone.Model class has an extend method on it 7:41 which will allow us to extend the Backbone.Model class 7:44 and add our own attributes and methods to it. 7:48 So the first thing we want to do is tell the note model how we want it to save itself. 7:51 In typical Backbone applications, this might be specifying a URL 7:56 that you can post and read from in order to update and retrieve information. 8:00 However, we're not using an external server. 8:05 Instead, we're using localStorage, so we're going to tell it for all of our Notes, 8:08 we want to use the app.store.notes datastore in order to persist the information. 8:12 And to do that, all we need to do is add the localStorage attribute 8:18 to our backbone model and give it the actual instance of our data store; 8:22 in our case, this App.stores.notes. 8:27 Now you can see why we needed to instantiate our App.store.notes 8:30 before we defined our model because this code will be executed right away 8:35 and we need to make sure that this instance is available. 8:39 So that's why we initialized our store before we did anything else. 8:42 So another thing that we can define in our extend object here is methods. 8:48 Now, there's a special method called initialize, which is called sort of like a constructor, 8:53 and this will be called any time we instantiate a new note object. 8:59 Now, it's optional for us to create this. 9:03 The intializer is great for things like initializing default values 9:05 or running any other logic 9:08 that needs to be run when we initialize a new note. 9:10 So what we're going to do is create an initialize method 9:13 and we do that by defining initialize as the function(){ 9:18 and the initialize function will actually receive any arguments passed to the note constructor. 9:22 Right now, we don't want to really capture any of those, 9:30 but we could if we needed to. 9:34 Now, when I set up my initializer, really want I want to do 9:37 is see if the title or body attributes have not been set, 9:40 and if they've not been set, I want to go ahead and set default values. 9:43 Now, we can set defaults in another way by defining a defaults attribute 9:48 in this, but the defaults that I want are a little more dynamic 9:52 so I'm going to set them in the initializer if they're not set by the user. 9:57 The first thing I want to check is if there's no title, so I'm going to use an if statement 10:02 and what I want to check is to see if there is no title set. 10:06 Now, in order to get attributes from a note, 10:11 I'm going to use the get method 10:14 and pass it the name of the attribute I want to get. 10:16 So what I can do is do (this.get( 10:19 and pass "title")) and that's how I would always retrieve the title attribute from my note. 10:23 Now, I want to check if it's non-existent, so I'm going to check as a negative 10:28 so that if this title does not exist, then I want to set the value, 10:32 and the way I set values or set attributes is the set method. 10:38 I use it like this: this.set. 10:42 Now, one thing that's easy to get tripped up on 10:45 is you may expect set to take two arguments-- 10:48 the first being the name of the attribute and the second being the value-- 10:50 but the way set actually works is it takes a JavaScript object 10:54 with keys and values, so even if you're setting one thing, 10:57 you need to use the object notation in order to do it. 11:00 It's very confusing if you've missed that part of the documentation. 11:04 So in order to set the title, I'm going to create a JavaScript object. 11:07 Its key is going to be {title: 11:11 and its value is what we want our default value to be, 11:14 so in our case, I'm going to create a string, 11:17 so we'll say "Note @ " 11:20 and let's add a date stamp to it + Date, so I'm just going to call Date() }) here 11:23 and this will create a string of Note @ and then some sort of time stamp. 11:30 Now, I also want to set a default value for our body 11:38 so we can see that there is no content in it, 11:41 and I'm going to do this much the same way. 11:44 In fact, I'll just paste this piece of code here 11:47 and we can see that I check if there's no body attribute, 11:48 I'm just going to set the body to the string "No Content"}). 11:52 So now we've seen how to get and retreive variables 11:56 and how to set default values. 12:00 This is all we need to define for our note right now. 12:03 Later on, we're going to be adding some other methods; 12:06 for instance, getting the geolocation information and some other nice utility functions, 12:09 but right now, that's really all we need from our note. 12:14 It's basically just and object that stores a value. 12:16 Now, it's going to be a few steps before we actually create our note 12:20 and see how it works, so what I'm going to do is I'm going to use the JavaScript console 12:24 in Chrome to sort of play around with this note API. 12:28 Right now, this note is sort of scoped locally so we can't actually access it 12:31 from our console, so what I'm going to do here is temporarily say: 12:37 window.Note = Note; 12:43 and this will make the global variable Note equal to our model. 12:48 So if we go back and refresh, we see we don't have any errors 12:53 and I'm just going to switch over to our console to get a much better view. 12:56 And so, we can see our Note is just a model, 13:01 so what we can do is say note = new Note 13:05 and we get our object back. 13:12 And what we can see is we can use note.get and pass it "title" 13:14 and we can see that our initializer actually worked. 13:21 We got note@ Mon Mar 14 and so on. 13:24 We could do note.get ("body"); 13:29 and we can see "No Content." 13:36 We could do note.set (title: "My Title")} 13:38 and then we can get the title again and see that it works. 13:48 I'm going to clear out the console here so we can see it again, 13:52 and now while our note object is storing values fine, 13:55 let's see how it works on persisting. 13:58 Now, what we need to do is simply call save on it 14:00 and what it should do is it should use its localStorage attribute, 14:03 which is the data store, and save itself in to that data store. 14:06 So we could do note.save-- 14:10 So it looks like there's a problem with the code that we initially downloaded for our app. 14:14 Problems like this can happen in real development situations, 14:19 and we could have tried to edit out every little problem that we encounter while developing, 14:22 but I think it's important to see the real problems and how they're solved. 14:26 Now, there was a change in how Backbone saves its data. 14:31 The localStorage adapter had already been updated 14:35 to reflect the change in how Backbone works. 14:37 However, the stable version of Backbone had not been released, 14:40 so our Backbone localStorage adapter is incompatible 14:43 with the version of Backbone we're using. 14:47 Now, this is easy to work around: we just need to get a slightly older version 14:49 of the localStorage adapter. 14:53 By the time this video was released, the Backbone localStorage and Backbone 14:55 may be in sync. 14:59 However, at the time that we filmed this, they're not. 15:01 The compatibie localStorage adapter file is included with the project code 15:03 available with this video. 15:07 So let's replace the incompatible code with the compatible localStorage code. 15:09 So what I'm going to do is I'm going to make sure that the original version 15:14 of our Backbone localStorage that I'm about replace it with is in our code, 15:18 so what I'm going to do is I have a version that I got 15:23 and I'm going to paste it into our Backbone localStorage file. 15:26 So switching over to our code, 15:31 the Backbone.localStorage file, 15:35 there are some changes here; you can see it has options.success. 15:38 Now, that's not going to work with our version of Backbone 15:44 so what I'm going to do is I'm going to replace this with our version, 15:46 and I'm going to make sure that the code has the correct version here 15:50 and you can tell it's the correct version because it says success with response (resp); 15:53 instead of options.success. 15:57 So I'm going to save this out and I'm also going to take our minified version of it 16:00 and right now, I'm just going to remove the selected file. 16:05 That means I'm going to delete it from our project 16:07 and that's because it's the compressed version of the wrong version 16:10 of our Backbone localStorage. 16:14 Now, we can compress it later and create our own minified version, 16:16 but this should work for now, so now we should have a working version 16:19 of our Backbone localStorage adapter, and let's go ahead and refresh. 16:23 Okay, so it looks like we have an unexpected token illegal 16:29 on Backbone.localstorage.js on line 20. 16:33 So--I wasn't getting this in my original one--let me just remove this code 16:36 and see if we can track down this error. 16:41 It's somewhere in those three lines of code, 16:44 so we take a look and we see this.name = name; 16:47 I don't see any problem there. 16:50 We see var Store = localStorage.getItem(this.name); 16:52 And then, this.data = (store && JSON.parse(store)) 16:57 or an empty variable {};. 17:04 It looks like the problem might be on this line, so let me remove that and refresh it. 17:06 So what is wrong with this line? 17:11 Okay, so I've looked at the code and it looks like we're erroring out 17:14 on this particular part right here--this JSON.parse and this (store). 17:17 And so what we can see is happening in here is it's getting the localStorage 17:22 and coded data for the (store), in our case, notes. 17:26 What happens if we call JSON.parse is we get syntax, unexpected token, illegal, 17:34 and that doesn't mean our code has an unexpected token. 17:40 That means the actual JSON.parse retreived bad code. 17:43 Now, the reason I think this might be happening 17:47 is that we might have loaded the wrong code, 17:50 and so whatever is stored in our storage under Notes is probably wrong, 17:53 which is cool; we can actually look into this using the Chrome Developers Tools. 17:58 I'm going to open up the Resources tab and actually close out our console here, 18:02 and we can look directly into our localStorage. 18:07 So our localStorage for localHost has notes 18:10 and looks like it also has notes for particular pieces 18:14 saved using their own id. 18:18 This might actually be wrong because the way I've seen my code when I was developing it, 18:21 all of the data was actually stored inside of the Notes key 18:26 as an encoded JSON string. 18:32 So it looks like the two different versions I tried were incompatible, 18:34 so I saved with the old version and I'm trying to retrieve with the new version, which is wrong. 18:37 So what I'm going to do is actually clear this out 18:43 so we can start from scratch and hopefully, now that I'm using a single version, 18:46 I'm not going to get errors when I'm transferring from one version of our localStorage code 18:51 to the other. 18:55 So I've now cleaned those out by using this simple delete button here. 18:56 Another way we could do it is from our console, 19:01 we could just call localStorage--which is our browser object for localStorage--.clear, 19:04 and this will clear out any localStorage data for this domain. 19:11 So we should be good. 19:17 Now, if we refresh, 19:19 I'm just going to create a New Note. 19:21 Let's go ahead set the title of my note. 19:24 Again, we can do note.get_title to see if that worked. 19:33 Awesome. 19:38 So finally, let's do note.save, 19:40 and it looks like it returns our note. 19:44 If we go back to our localStorage here and refresh it, 19:48 we can see that our localStorage now has a key of notes 19:52 and an object here, which is serializing our note object 19:56 and giving it a unique id. 19:59 These unique ids are generated randomly and will uniquely identify each note 20:01 in our database. 20:06 So the key is our note id and the value is a JSON-encoded representation of our note. 20:08 So even if we refresh the page, we can see that our data is still stored in the database 20:15 and we should be able to get our notes out. 20:20 We'll look at how we can actually retrieve our notes 20:22 when we take a look at collections next. 20:25
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