To keep things simple, I believe the model should represent both the server-side model and the client-side view state, distinguishing the view state attributes by a preceding _. The view state attributes are ignored by the server when saving the model.
Here's an simplified example of the workflow I use:
var animal = new View({
initialize: function(){
// define the model and default view state when view is initialized
this.model = new Model({id:3, _edit:false}, {url:'/animals'));
}
, render: function(){
var self = this;
this.undelegateEvents();
this.delegateEvents({
'click [data-trgger]': function(e){
self[$(e.currentTarget).attr('data-trigger')].apply(this);
}
});
var success = function(){
// pass the model to the template engine
self.$el.html( _.template('#edit-animals', {model: self.model}) );
}
// fetch the model from the server when view is rendered
// you could check if the model is already fetched
this.model.fetch({success:success});
}
, onSave: function(){
// save the model then:
this.model.set('_edit', false);
this.render();
}
, onEdit: function(){
this.model.set('_edit', true);
this.render();
}
});
And the template:
<% if(model.get('_edit')){ %>
<!-- the view is in 'edit' state, show input and save button -->
<div>
<input type="text" name="breed" class="form-control">
</div>
<button class="btn btn-primary" data-trigger="onSave">Save</button>
<% }else{ %>
<!-- the view is in 'read-only' state, show values and edit button -->
<button class="btn btn-default" data-trigger="onEdit">Edit</button>
<div>
<%= model.get('breed') %>
</div>
<% } %>