Backbone.js: how to embed model attribute editing

how to add in-line editing of model attributes,

for example, when I have a Player model

 var Player = Backbone.Model.extend({ defaults: { id: 0, name: '', points: 0 }, initialize: function(){ // irrelevant stuff happening here... }, rename: function(newName){ this.set({ name: newName }); } }); 

and a playerRow view

 var PlayerRow = Backbone.View.extend({ tagName: 'li', className: 'player', events: { 'click span.score': 'score', 'blur input.name': 'rename', 'click div.playername': 'renderRename' }, initialize: function(){ _.bindAll(this, 'render', 'rename'); this.model.bind('change', this.render); }, render: function(){ var template = Tmpl.render("playerRow", { model : this.model }); $(this.el).html(template); return this; }, renderRename: function() { // i was thinking of switching the DOM into a textfield here }, rename: function(){ var inpt = $(this.el).find('input.name'); var newName = (inpt.val() != '') ? inpt.val() : 'no-name'; this.model.rename(newName); } }); 

and my playerRow template

 <script type="text/template" id="playerRow-template"> <% if ( model.get('name') == '' ) { %> <div class="state-edit"><input type="text" class="name" name="name"></input></div> <% } else { %> <div class="playername"><%= model.get('name') %></div> <% } %> </script> 

or I set a specific property of my model that contains the state (by default or editing) that triggers re-rendering and in my template instead of testing if name == '' I can check this state property.

or am I doing this inline, as I say in my comment on renderRename, I just change the DOM to the input field, but I think this is a bad way to do this. Will this cause problems with already related events? e.g. 'blur input.name': 'rename'

I doubt that creating a new view for editing is the best way because I want inline editing only for this name field, I don’t want all other player templates to be duplicated in the player template and the editplayer template.

so, bottom line, my question is: what is the best way to handle inline editing

  • separate presentation
  • inline just adds an input field (I don't know if this works well with related events)
  • when my model contains a state variable for this attribute (it will work, but it sounds strange to have data related to the model view).
+4
source share
2 answers

A completely different option:

Native editing using the html EditableContent function. There is no need to modify / clutter the DOM, an excellent user interface, if done correctly, is supported in all major browsers.

Several js editors use this, primarily the Aloha Editor (check browser support), but for editing attributes without the need for much more (for example, editing extended text, etc.), you can easily collapse your own.

EDIT: June 2012:

Rolling makes it a lot easier with the excellent library: http://code.google.com/p/rangy/

Hth, Geert Yang

+9
source

I like to have an extra input field in the view, which is hidden by default. (This is closest to your option (2), but it allows you to avoid conventions in the template or add elements on the fly.)

So the template might look something like this:

 <div class="show-state"> ... <%= name %> ... <input type="button" value="edit"/> </div> <div class="edit-state"> <!-- hidden with display: none in CSS --> ... <input type="text" value="<%= name %>"/> ... </div> 

Essentially, this is a two-state view, "show" and "edit." When the user clicks β€œedit,” I call this.$('.show-state').hide(); this.$('.edit-state').show(); this.$('.show-state').hide(); this.$('.edit-state').show(); to flip the state.

After editing is sent or canceled, I only have to look at the reders (after talking to the server and updating the model attributes if necessary) to return to the initial state β€œshow” and reset the input field.

PS Keep in mind that my code includes XSS because it does not exit name .

0
source

All Articles