Let's build the client for our feature List projects
. Each item in the list consists of a project name and an edit and delete button. Clicking on the name will display a list of repositories; clicking on edit will display an inline form populated with the models' data, and clicking on delete will delete the item from our database. We will return to hook up these three functions later. For now, we will simply display a project list.
What follows is an HTML template ./templates/projects.hbs
for a project item; it contains a placeholder {{_id}}
, which will be replaced by our Backbone application:
<a href="#{{_id}}" data-id="{{_id}}">{{name}}</a> <button class="delete btn btn-mini btn-primary list-btn">del </ button> <button class="edit btn btn-mini btn-primary list-btn spacer ">edit e</button>
Let's define a skeleton Backbone application with all of its pieces in place: ./public/components/vision/vision.js
. We start by defining the Vision
namespace; we add to it an outer function called Application
, that has a single method called start
. Here we instantiate a router
and call Backbone.history.start()
in order to start the Backbone application. We then call router.navigate('index', true)
and navigate to our home page. With this function in place, we instantiate new Vision.Application()
and call start()
.
var Vision = Vision || {}; Vision.Application = function(){ this.start = function(){ var router = new Vision.Router(); Backbone.history.start(); router.navigate('index', true); } }; $(function(){ var app = new Vision.Application(); app.start(); });
Let's now create the application Router
. Generally, Backbone applications only have one of these; a router is the entry point for our application.
First we add a function Router
, which extends the Backbone Router
type. We add a view for our list of projects called projectListView
, and add a routes
hash, which defines a single route. The entry point for our application is an empty route mapped to a method called index
. The initialize
or constructor method is called when the router is instantiated; from here we call a method project
, which instantiates a ProjectListView
. The index
method, which matches the route as defined previously, renders our view by calling projectApplication.render()
.
Vision.Router = Backbone.Router.extend({ projectListView : "", routes: { "" : "index", }, initialize : function(){ this.project(); }, project : function(){ this.projectListView = new Vision.ProjectListView(); }, index : function(){ this.projectListView.render(); } });
Let's implement our Project
model to support our view. We start by adding a function Project
, which extends the Backbone Model
type and includes a hash of default values for the two properties in our model. We override the idAttribute
parameter in order to accommodate MongoDB identifiers. We will use the MongoDB _id
as our model identifier; by default Backbone will use id
. This identifier will be appended to any request Backbone makes to the server, for example, when performing GET, POST, PUT, or DELETE. We already added the API for this model in Chapter 2, Building a Web API. The urlRoot
parameter links this model to the web API route /project
to return a project.
Vision.Project = Backbone.Model.extend({ defaults: { id : "" , name: "" }, idAttribute: "_id", urlRoot: '/project' });
Let's implement a collection; ProjectList
for our Project
model. We add a function, ProjectList
, that extends the Backbone Collection
type and we specify model type as Vision.Project
. We add a url
method which returns our web API route /project
to return a list of projects. The initialize
method is called when the collection is instantiated; from here we do our initial fetch()
to get our projects; thus calls the API /project
.
Vision.ProjectList = Backbone.Collection.extend({ model: Vision.Project, url: function () { return "/project/"; }, initialize: function() { this.fetch(); } });
Before we implement ProjectListView
, let's create event_aggregator
; this will allow our views to trigger and bind named events that other views can respond to. We will need to do this in order for ProjectListView
to inform RepositoryListView
that it's time to display a RepositoryList
.
Let's add an event_aggregator
function to the Backbone view prototype using the underscore.js
extend method to mix in the Backbone event
module into our views:
Backbone.View.prototype.event_aggregator = _.extend({}, Backbone.Events);
Let's implement a view for our Project
collection— ProjectListView
. We start by defining a function ProjectListView
which extends the Backbone View
type, and add a Projects
array for our project list. We assign a DOM element to el
; an unordered list called projects-list
. This is the element our view will be inserted into. Backbone will construct an empty div
tag if you do not assign it to el
.
The initialize
method is called when the view is instantiated; here we instantiate a new ProjectList
, passing our Projects
array. We then call collection.on('add')
, which upon fetching data from the API will call the add
method. The add
method instantiates ProjectView
, passing to it a project
model. We then append ProjectView
to our DOM element via $el
and return the view.
Vision.ProjectListView = Backbone.View.extend({ Projects: [], el: $("ul#projects-list"), initialize: function () { this.collection = new Vision.ProjectList(this.Projects); this.collection.on('add', this.add, this); }, add: function (project) { var projectView = new Vision.ProjectView({ model: project }); this.$el.append(projectView.render().el); return projectView; } });
We complete this section by implementing a view for a single project—ProjectView
. We start by defining a function ProjectView
, which extends the Backbone View
type, and add a tagName
and assign li
to it. This tag will be wrapped around our project view; our DOM element is a ul
tag.
We then include viewTemplate
and assign our precompiled handlebars template to it. Although the templates are compiled to a single file —./vision/templates.js
— we still refer to the template by name; templates/projects.hbs
. The render
method renders the view; we pass the project
model to our viewTemplate
, which is then added via $el
to our DOM element and we return the view:
Vision.ProjectView = Backbone.View.extend({ tagName: "li", viewTemplate: visiontemplates["templates/projects.hbs"], render: function () { var project = this.viewTemplate(this.model.toJSON()); this.$el.html(project); return this; } });
If you go into MongoDB and add the following record to the projects collection in the vision database, when visiting the Vision application in a browser you can see this record in the project list view:
{ "_id" : ObjectId("525c61bcb89855fc09000018"), "created" : ISODate("2013-10-17T22:58:37Z"), "name" : "test name", "token" : "#TOKEN#", "user" : "#USER#" }
3.147.65.247