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.
18.220.163.91