Search code examples
javascriptjquerybackbone.js

Set an Active property to only 1 model in a Backbone Collection at any time


I have a collection of Backbone models. I want to set a model property to 'active' but make sure that only 1 model can be active at a time. I have not been able to get this to work and am looking for some guidance.

Here is a fiddle to my code: http://jsfiddle.net/doen1mm9/

Here is my JavaScript and Templates.

JS:

var data = [
    {
        "color": "blue",
        "name": "Johnny"
    },
    {
        "color": "green",
        "name": "Melissa"
    },
    {
        "color": "yellow",
        "name": "Bill"
    }
];

var TheModel = Backbone.Model.extend({
});

var TheCollection = Backbone.Collection.extend({
    model: TheModel,

    initialize: function() {
        this.on('change:isActive', this.ensureSingleActive, this);
    },

    ensureSingleActive: function(current) {
        var previous = this.findWhere({isActive: true});

        if (previous !== undefined) {
            previous.set('isActive', false);   
        }

        current.set('isActive', true);
    }
});

var ListView = Backbone.View.extend({
    el: '.js-container',

    tagName: 'ul',

    render: function() {
        this.collection.each(function(item) {
            var listItemView = new ListItemView({model: item});
            this.$el.append(listItemView.el);
        }, this);
    } 
});

var ListItemView = Backbone.View.extend({

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

    tagName: 'li',

    template: _.template( $('#item-template').html() ),

    render: function() {
        var temp = this.template({model: this.model.toJSON()});

        this.$el.html( temp );
    },

    events: {
        'click': 'toggleActive'   
    },

    toggleActive: function(e) {
        this.model.set('isActive');
        console.log(this.model.toJSON());
    }
});

var theCollection = new TheCollection(data);

var listView = new ListView({collection: theCollection});
listView.render();

Template:

<div class="js-container"></div>

<script type="text/template" id="item-template">
    <span <% if (model.isActive === true) { %> class="active" <% } %>>
        <%- model.name %>
    </span>
</script>

Solution

  • Try this http://jsfiddle.net/ManikandanK/c477rone/1/ There are two things you need to correct.

    ensureSingleActive: function(current) {
        if(current.get('isActive') ) {
    
            var previous=   _.find(this.models, function(model) {
                return model != current && model.get('isActive') 
            });
    
        if (previous) {
            previous.set('isActive', false);   
        } 
    }
    }
    

    When you are inside this function, already current model value is already set. so you dont need to set the value again. You missed to pass the value to set function.

    this.model.set('isActive', true);