Search code examples
jquerybackbone.jsbackbone-views

Refresh the table view on collection.fetch() method


Consider following Scenario:-

- Model of a Player

 var Player = Backbone.Model.extend({
         defaults: {
PlayerId: 0,
PlayerName: "",
IsActive: false
}
    });

Collection Model is as follows:

 var PlayerList = Backbone.Collection.extend({
            model: Player,
            url: '/Match/GetPlayers/'
        });

List View is as follows:

 var ListView = Backbone.View.extend({
        el: '#ListContainer',
        initialize: function () {
            _.bindAll(this, 'render');
            this.collection.on('reset', this.render);


        },
        render: function () {
            if (this.collection.length > 0) {
            this.collection.each(this.AppendPlayer, this);
            }
            return this;
        },
        AppendPlayer: function (data) {
            var palyerView= new PlayerView({ model: data });
            $(this.el).find('table').append(genreView.render().el);

        },
        events: {
            "click #btnplay": "CheckStatus"
        },

        CheckStatus: function () {

            // alert();
           //here i will make a ajax call and get update the status of player
             which comes from other REST service.
        }


    });

Below is the PlayerView:

var PlayerView = Backbone.View.extend({
        tagName: "tr",            
        template: _.template($("#player-Template").html()),
        render: function () {

            this.$el.html(this.template(this.model.toJSON()));

        return this;
    }
    });

HTML is as follows:

<div id="ListContainer">
    <input type="button" id="btnplay" value="StatusCheck" />
    <table id="myTable">
        <tr>
            <td>Player Id</td>
            <td>Name</td>
            <td>Statu</td>
        </tr>

    </table>
</div>
<br />
<br />

<script id='player-Template' type='text/template'>
    <td><%=PlayerId%></td>
    <td><%=PlayerName%></td>    
    <td><%=IsActive%></td> 
</script>

so when i click the "Play" button it calls my API service and gets me an updated collection.

and i try to refresh the collection and the view using below logic:

PlayerList.fetch({
                    success: function (collection, resp) {
                        //console.log('success' + resp); //

                    },
                    error: function (er) {
                        console.log('error: %o', er)
                    },
                    reset: true,

                });

I get the updated model back but what happen is the updated model get's appended with the existing rows.

I need to clear the existing rows and repopulate it with my new collection.

Any help would be great.


Solution

  • empty() the table inside the render method:

    render: function () {
      this.$el.find('table').empty(); // clears existing rows 
      if (this.collection.length > 0) {
         this.collection.each(this.AppendPlayer, this);
      }
      return this;
    }
    

    BTW, you don't have to do $(this.el), backbone provides a jQuery instance of your view's element via this.$el.

    Unless you're reusing the AppendPlayer (I suggest using camelCase for method names. Use pascal case only for constructor functions) method, you can simply do the following:

    render: function() {
      var $table = this.$el.find('table');
      $table.empty();
      if (this.collection.length) {
        this.collection.each(function(model) {
          $table.append(new PlayerView({
            model: model
          }).render().el);
        });
      }
      return this;
    }
    

    and if you modify the playerView to render itself as shown below:

    var PlayerView = Backbone.View.extend({
      tagName: "tr",
      template: _.template($("#player-Template").html()),
      initialize: function() {
        this.render();
      },
      render: function() {
        this.$el.html(this.template(this.model.toJSON()));
        return this;
      }
    });
    

    You can just do:

    render: function() {
      var $table = this.$el.find('table');
      $table.empty();
      if (this.collection.length) {
        this.collection.each(function(model) {
          $table.append(new PlayerView({
            model: model
          }).el);
        });
      }
      return this;
    }
    

    Side note: you seems to be creating palyerView but you're appending genreView ..?!