Drejc
Drejc

Reputation: 14286

Simple backbone example not updating view

I'm starting to learn Backbone with this simple example:

<div id="counter">unkown</div>
<button id="add-button">ADD</button>

(function($){

   var Counter = Backbone.Model.extend({
     defaults: {
        count: 0            
     }
   });

   var CounterView = Backbone.View.extend({
       el: "#counter",

       events: {
            "click #add-button": "add"
       },

       add: function() {
           this.model.count++;
           render();
       },

       render: function() {
           $(this.el).text(this.model.get("count"));
           return this;
       },

       initialize: function(){              
           this.render();
       }
   });

   var counterItem = new Counter();
   var counterView = new CounterView({model: counterItem});              

}(jQuery));  // function($)

So when the "Add" button is pressed the counter should increase and the view should be updates. I have binded the view and the model and have the click event linked with the add function, but somehow this is not working.

So I guess I'm doing something wrong or I'm just missing some binding?

EDIT: Fixed as suggested to this ... still not working:

<div class="list">
        <div id="counter">unkown</div>
        <button id="add-button">ADD</button>
</div>  

    (function($){

       var Counter = Backbone.Model.extend({
         defaults: {
            count: 0            
         }
       });

       var CounterView = Backbone.View.extend({
           el: "#counter",

           events: {
                "click #add-button": "add"
           },

           add: function() {
               alert("ADD");
               this.model.set("count", this.model.get("count") + 1);
               this.render();
           },

           render: function() {
               $(this.el).text(this.model.get("count"));
               return this;
           },

           initialize: function(){               
               this.render();
           }
       });

       var counterItem = new Counter();
       var counterView = new CounterView({model: counterItem});                     

    }(jQuery));  // function($)

EDIT: FIXED AND WORKING

<div id="counterHolder">
        <div id="counter">
            <span>unknown</span>
           <button id="add-button">ADD</button>
       </div>
    </div>

    <script>


    (function($){

       var Counter = Backbone.Model.extend({
         defaults: {
            count: 0            
         },

         increase: function(){
             this.set("count", this.get("count") + 1);
         }
       });

       var CounterView = Backbone.View.extend({

           el: "#counter",

           events: {
                "click #add-button": "add"
           },

           add: function() {
               this.model.increase();               
           },

           render: function() {
               $("#counter span").text(this.model.get("count"));
               return this;
           },

           initialize: function(){
               this.render = _.bind(this.render, this); 
               this.render();
               this.model.bind('change:count', this.render);
           }
       });

       var counterItem = new Counter();
       var counterView = new CounterView({model: counterItem});                     

    }(jQuery));  // function($)

    </script>

Upvotes: 1

Views: 3433

Answers (3)

Paul
Paul

Reputation: 18597

The button must be a descendant of the view's el

Update your html like below and it should work

<div id="counter">
  <button id="add-button">ADD</button>
</div>

If you still want to display the count, then add an additional span

<div id="counter">
  <span id="count" />
  <button id="add-button">ADD</button>
</div>

And update your render method

render: function() {
  this.$('#count').text(this.model.get("count"));
  return this;
}

Upvotes: 5

oh_cripes
oh_cripes

Reputation: 107

I think your mistake is a simple javascript error. In add you need to call this.render() not just render().

Upvotes: 0

Peter Lyons
Peter Lyons

Reputation: 146034

Backbone models must have their data manipulated through the get and set methods, not as regular javascript objects. Try

this.model.set("count", this.model.get("count") + 1);

Or better yet, add an increment method to your model class that updates the attribute via get and set for better encapsulation.

Also, just a note on convention that typically every piece of the DOM that a view changes or binds to should be contained within the parent el element. Your view is binding to the add button which is not contained within the view's parent div. It seems to be working, but it's basically the event handling equivalent of a global variable.

Upvotes: 0

Related Questions