Feature: List projects

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#"
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.65.247