Search code examples
javascriptbackbone.jsmarionette

Updating a LayoutView's Model


JSBin link

Click the 'Clicks' link to see the console showing updated model data, but the original displayed HTML doesn't change.

Updating the model on the LayoutView doesn't seem to cause the view to update the displayed data. I thought that was part of the default interaction between Views and Models.


Solution

  • Backbone and Marionette do not bind model data to views automatically. You will have to listen that model to change within the view and update it.

    For example, you can simply re-render the view completely when any data within the model changes:

    initialize: function(){
        this.listenTo( this.model, "change", this.render );
    }
    

    Or create a listener for a specific piece of data expected to change, and only update part of the view. This is preferred if the view is more complicated:

    onRender: function(){
        this.listenTo( this.model, "change:value", this.renderValue );
    },
    renderValue: function(){
        /* This expects that you wrap the value with
           <span class="value"></span>
           in the template */
        this.$('.value').text( this.model.get('value') );
    }
    

    Here's a complete working example:

    var TestLayoutView = Mn.LayoutView.extend({
        template: '#lvTemplate',
        el: '#app',
        events: { 'click .watchhere': 'updateValue'},
        onRender: function(){
            this.listenTo( this.model, "change:value", this.renderValue );
        },
        renderValue: function(){
            this.$('.value').text( this.model.get('value') );
        },
        updateValue: function (clickedView) {
            this.model.set('value', this.model.get('value') + 1);
        }
    });
    
    var testLV = new TestLayoutView({
      model: new Backbone.Model({ value: 15 })
    });
    
    testLV.render();
    <script src='http://code.jquery.com/jquery.js'></script>
    <script src='http://underscorejs.org/underscore.js'></script>
    <script src='http://backbonejs.org/backbone.js'></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/backbone.marionette/2.4.2/backbone.marionette.js'></script>
      
    <script type="text/template" id="lvTemplate">
      <a class='watchhere' href="#">Clicks <span class="value"><%= value %></span></a>
    </script>
      
    <div id="app"></div>