2
votes

I am a backbone newbie and I am trying to develop a Todo like App.

I have a Main view which is a list view and it has subviews. - the subview content can be edited on double click and it would get saved when the enter key is pressed. - very similar to todo example given in backbone github code.

var SubView = Backbone.View.extend({
    tagName: "li",    
    events: {
        "dblclick"              : "show_edit_view",
        "blur .element"         : "close_edit_view",
        "keypress .element"     : "save_edit_view",
        "click button.remove"   : "remove_question"
    },
    initialize: function(){
        this.render();             
        this.listenTo(this.model, "change", this.render);
    },
    render: function(){        
        this.$el.html(_.template($("#sub_view_template").html(),this.model.toJSON()));
        return this;
    },
    show_edit_view: function() {
        this.$el.find("div.view").addClass("no_show");
        this.$el.find("input").removeClass("no_show");
    },
    close_edit_view: function(){
        this.$el.find("div.view").removeClass("no_show");
        this.$el.find("input").addClass("no_show");
    },
    save_edit_view: function(e){
        if (e.keyCode == 13) {            
            this.model.save({name: e.currentTarget.value});
            this.close_edit_view();
        }
    }
}); 

And the template for this is

<script id="sub_view_template" type="text/x-template">
   <div class="view"><%= name %></div>
   <input class="element no_show" value="<%= name %>" type="text" /> <button class="remove">Remove</button>
</script>  

This one works fine, the model is updated in the view and the update post request is sent to the server.

But, when I change the initialization and save_edit_view functions, only the first change event is fired and not the change events.

initialize: function(){
    this.render();             
    this.listenTo(this.model, "change", this.render);
    this.input = this.$("input.element");
},
save_edit_view: function(e){
    if (e.keyCode == 13) {            
        this.model.save({name: $(this.input).val()});
        this.close_edit_view();
    }
}

I was wondering what could the problem be?

Thanks for any help!!!

2
How many times do you call render?mu is too short
don't call .render() function inside the .initialize() method. render is supposed to be called outside the view, and just instantiating on view should not mean rendering.Alexander Beletsky
@alexanderb Because the subview is not assigned to any existing element - I thought it would be better to call render in initialize function. - I guess, I can avoid writing an object for it. that was my intention. But, for those views which are bound to an existing element in the dom, I always call render separately.Ajeesh Joshy
@muistooshort Well, for the subview render is only called in the initialize function.Ajeesh Joshy
Right, el's content generally changes inside render so anything that references the content of el should also go inside render. Or don't bother caching the references at all, it is rarely worth the trouble if you use this.$() to properly localize your searches.mu is too short

2 Answers

1
votes

The problem is you are referring to only one object. This means when you make the assignment:

this.input = this.$('input.element'); // match the current elements.

You are only getting the value from that exact object. After the first change, this.input is not the same object that contains your new value, and fails to save the model with a new value.

A demonstration that may help:

console.log(this.$('input.element') != this.$('input.element')); // true

This is why the following would work:

save_edit_view: function(e){
  if (e.keyCode == 13) {            
    this.model.save({name: this.$('input.element').val()});
    this.close_edit_view();
  }
}
1
votes

I guess this.$("input.element"); refers to the first item from the list. And when you first time change model value with the value from the first item it works. But second time it doesn't works because the value of the first item still the same. That is why you have to get input value from the event - e.currentTarget.value