Feature: Create a project

Let's add a project form for our feature Create a project. It consists of a large Add project button, a text box for our project name, and save and cancel buttons. Clicking on save will POST the project to our Express server, whereas, clicking on cancel closes the form.

What follows is an HTML template ./templates/project-form.hbs for a repository item:

<form class="form-inline">
  <ul class="errors help"></ul>
  <label>name</label>
  <input class="name" placeholder="project name" required="required" value="{{name}}" autofocus />
  <br/><button class="cancel btn btn-mini btn-primary form-btn">cancel</button>
  <button class="save btn btn-mini btn-primary form-btn form-spacer">save</button>
</form>

Let's make a few changes to router and wire up a route to our Add Project button. routes now includes a route called add, which calls a method called add. We include an add method that calls projectListView.showForm(), rendering our form:

    routes: {
      "" : "index",
      "add" : "add"
    },
    add : function(){
      this.projectListView.showForm();
    }

Let's make some changes to projectListView and modify the initialize method. We bind this view to the reset, add, and remove events of the collection. We also add a showForm method as called in the preceding code. The method renders a project form by calling this.add(), passing new Vision.Project(), and calling add() on the view returned.

initialize: function () {
  this.event_aggregator.on('repository:join', this.repository, this);
  this.collection = new Vision.ProjectList(this.Projects);
  this.collection.on('reset', this.render, this);
  this.collection.on('add', this.add, this);
  this.collection.on('remove', this.remove, this);
},

showForm: function () {
  this.add(new Vision.Project()).add();
}

Let's add some validation to our Project model so we can validate form input for our project. We add a validate method to our Project model and validate our Project model's name. If validation fails, we return an errors array containing error messages. We are actually overriding the validate method. Backbone.js requires that you override the validate method with your custom validation logic. By default, the method validate is also called as part of a save call.

validate: function(attrs) {
  var errors = [];
  if (attrs.name === '') errors.push("Please enter a name");
  if (errors.length > 0) return errors;
}

Let's make some changes to projectView. We start by adding a new template called formTemplate, which displays a form for adding a new project. We add two new events to the events hash—a button save event and a button cancel event.

The cancel method, which responds to the cancel event, will get the current projectId from our model and check if the model.isNew. If it's new we simply remove the projectView from our projectListView. If its not new, we render our view and also render repositoryListView by calling repository. We then navigate to the index page using history.navigate.

The save method, which responds to the save event, grabs projectId from our model and the form data. We then call model.isValid, which calls the validate method in our project model. Any error returned results in calling formError. If the model is valid, we go off and get our selected repositories and assign this to our form. We then attempt to save the form as Project with a call to model.save. Any error returned results in calling formError. A successful save enables us to render the project in ProjectListView. We also render RepositoryListView by calling repository. We then navigate to the index page using history.navigate.

formTemplate: visiontemplates["templates/project-form.hbs"],

events: {
    "click a" : "repository"
    "click button.save": "save",
    "click button.cancel": "cancel"
},

add: function () {
    this.$el.html(this.formTemplate(this.model.toJSON()));
    this.repository();
},

cancel: function () {
    var projectId = this.model.toJSON()._id;

    if (this.model.isNew()) {
      this.remove();
    } else {
      this.render();
      this.repository();
    }

    Backbone.history.navigate('index', true);
},

  save: function (e) {
    e.preventDefault();

    var me = this
    , formData = {}
    , projectId = this.model.toJSON()._id;

    $(e.target).closest("form")
    .find(":input").not("button")
    .each(function () {
      formData[$(this).attr("class")] = $(this).val();
    });

    if (!this.model.isValid()) {
      me.formError(me.model, me.model.validationError, e);
    } else {
      formData.repositories = $('#repository-list')
      .find("input:checkbox:checked")
      .map(function(){
      return $(this).val();
    }).get();
  }

  this.model.save(formData, {
    error: function(model, response) {
      me.formError(model, response, e);
    },
    success: function(model, response) {
      me.render();
      me.repository();
      Backbone.history.navigate('index', true);
    }
  });
},

formError: function(model, errors, e) {
  $(e.target).closest('form').find('.errors').html(''),

  _.each(errors, function (error) {
    $(e.target).closest('form').find('.errors')
    .append('<li>' + error + '</li>')
  });
}

You will now be able to complete the form and add a new project.

..................Content has been hidden....................

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