1

Am trying to update the some of the columns in table view when a timer triggered on collection am getting a subset of (only changed) properties. tried all kinds of codes from google but no luck.

Want to update only age property out of name and designation in view not intended to rerender the entire view.

here is my code

<div class='mainBody'>
        <table class="table">
            <tr class="success">
                <td>Name</td>
                <td>Age</td>
                <td>Ocupation</td>
            </tr>
        </table>
    </div>

    <script id="externalViewTemplate" type="text/template">

            <td width='25%'> <%= name %> </td>
            <td width='25%' id="age"> <%= age %> </td>
            <td width='25%'> <%= occupation %> </td>
    </script>

Script:

    //Person Model
var PersonModel = Backbone.Model.extend({
    _id:"id"
});

//Person collection - People
var PeopleCollection = Backbone.Collection.extend({
    model: PersonModel,
    view: PeopleView,
    initialize: function(){
        this.updateAge = setInterval(this.getAge.bind(this), 3000);
    },

    getAge: function()
    {
        var per = [{
                        id:1,
                        age: 31
                    },
                    {
                        id:2,
                        age: 32
                    },
                    {
                        id:3,
                        age: 37
                    }];
        this.reset(per);          
    }
});

//Person view - Responsible for rendering one person
var PersonView = Backbone.View.extend({
    tagName: 'tr',
    template: _.template( $('#externalViewTemplate').html() ),
    initialize: function() {
        this.model.on("change:age", this.update, this);
    },

    update: function() {
        this.el.cells["age"].innerHTML = this.model.get("age");
    },

    render: function(){
        this.$el.append(this.template(this.model.toJSON()));
        //console.log(this.$el.find('.edit'));
        return this;
    }
});

//person view collection - rendering the rows collection
var PeopleView = Backbone.View.extend({
    view: PersonView,
    initialize: function(options){
        this.collection = options.collection,
        this.collection.on("reset", this.update, this);
    },
    render: function(){
        this.collection.each(function(person){
            var personRow = new PersonView({model: person});
            this.$el.append(personRow.render().el);
        }, this);
    },

    update: function(){
        this.collection.each(function(person){
            //var personRow = new PersonView({model: person});
            this.model.age = person.age;
        }, this);
    }
});


//Try this code

var personCollection = new PeopleCollection([
    {
        id:1,
        name: 'Raju',
        age: 31,
        occupation: 'Dotnet Programmer'
    },
    {
        id:2,
        name: 'Rajesh',
        age: 32,
        occupation: 'Developer'
    },
    {
        id:3,
        name: 'Ramesh',
        age: 33,
        occupation: 'Designer'
    }
]
);

var peopleList = new PeopleView({ el: '.table', collection: personCollection});
peopleList.render();

Want to update only age property out of name and designation in view not intended to rerender the entire view.

user3625533
  • 339
  • 1
  • 4
  • 20

1 Answers1

2

According to <tr> - MDN cells property returns an HTMLCollection. Your code for updating a cell should be

update: function() {
    this.el.cells.namedItem("age").innerHTML = this.model.get("age");
    // or this.el.cells.item(1).innerHTML = this.model.get("age");
    // this.el.cells[1].innerHTML = this.model.get("age"); might work
},

Since you most likely has jQuery with backbone, you can just do

this.$el.find(".age").text(this.model.get("age"));

Note that I use className "age" because you shouldn't use id in templates which gets duplicated. You can also use index(), eq() etc to access the cell using jQuery instead of className

T J
  • 42,762
  • 13
  • 83
  • 138
  • 1
    I just want to add a disclaimer: on big tables, making lots of read and write calls in succession will really slow down the rendering to a point where a complete [_efficient re-render_](https://stackoverflow.com/a/44034868/1218980) would be better. – Emile Bergeron Oct 23 '17 at 15:21
  • same thing iam doing in personview update method. My question in person collection getAge method will run on timely basis and i have to update the existing collection with new values for age property. How can i update the existing collection object with the data received. am doing 'this.reset(new object)' after i get the new object with modified ages. This is not working how can i change every model in collection so that my view already listening to the model changes and renders the updated models? – user3625533 Oct 24 '17 at 06:15
  • @user3625533 You should update model like `this.model.set("age", person.age);` instead of `this.model.age = person.age;` for the listeners to work. But noticing that you have `this.model` and `this.collection` in the same view, something is wrong with your structure. Can you share a demo in a stack snippet or fiddle? – T J Oct 24 '17 at 09:51
  • @user3625533 You should keep a references to the item views in an array in the collection view when you create them. Then in your collection view's update you should do something like `this.itemViews.each(function(personView){ personView.update(); })` Assuming `personView` correctly holds reference to updated model as `this.modal` via object reference it should work. – T J Oct 24 '17 at 09:56