Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a dynamic property on a model with Backbone.js

Story: I have a lot of properties that needs to be set. Since they have similarities I choose to read out the class the inputbox is part of as property name.

Problem: A dynamic property of an object can be set, just like an associative array. So I could do

var customattribute = this.$el.parents('div').attr('id');
var value = $(e.currentTarget()).val();

this.model.attributes[customattribute] = value;

But this wouldn't trigger a change event of the model. I could manually trigger a change event, but this wouldn't update this.model.changedAttributes(), I need to set only the changed attribute, not every attribute.

This of course doesn't work either:

this.model.set(customattribute: value);

So how would I handle this problem?

I have ALOT (200+) attributes that can be set, I wouldn't like to make separate eventlisteners for every attribute unless thats the only way.

Code:

var Display = Backbone.View.extend({
    className: 'display',
    events: {
        'slide .slider' : 'sliderHandler'
    },
    initialize: function(){
        _.bindAll(this, 'render', 'sliderHandler','update');
        this.model.on('change',this.update, this);
    },
    render: function(){
        this.$el.html(_.template(html, {}));
        this.$('.slider').slider();

        return this;
    },
    sliderHandler: function(e){
        var slider = $(e.currentTarget);
        var property = slider.parents('div').attr('id');
        var value = slider.slider('value');

        this.model.attributes[property] = value;            
    },
    update: function(){
        console.log(this.model.changedAttributes());
        //get changed attribute + value here

    },
});

Edit:

The two answers below solved it. Map the attributes to an object and give that to Backbone. Also I found another solution. Instead of an object, model.set() also accepts an array.

model.set(customattribute, value, customattribute2, value2);
like image 773
Jareish Avatar asked Mar 09 '12 20:03

Jareish


2 Answers

I'm not sure that I fully understand your problem, but: If you want to update an attribute, just:

this.model.set({
     customattribute: value
});

If you want that the setting not trigger an event, you could pass a silent option, like this:

this.model.set({
     customattribute: value
}, {silent:true});

I hope it helps you.

UPDATED:

Another way:

 var map = {};
 map[customattribute] = value;
 this.model.set(map);
like image 57
Aito Avatar answered Nov 20 '22 11:11

Aito


You need to do this

var attributeName = this.$el.parents('div').attr('id');
var value = $(e.currentTarget()).val();
var attribute = {};
attribute[attributeName] = value;
this.model.set(attribute);

if attribute was "test" and value 'value' it would be the same as

this.model.set({test: 'value'});

which is what correctly sets the attribute and propagates to your view thanks to model change event

like image 5
James Kyburz Avatar answered Nov 20 '22 11:11

James Kyburz