3

I have a backbone.js model similar to the one shown below.

Filters = Backbone.Model.extend({
    defaults : {
        title: [ ["title1", "easy"], ["title2", "hard"] ]
    }
});

I'm trying to add an element to the first-level array, such that the model then becomes:

Filters = Backbone.Model.extend({
    defaults : {
        title: [ ["title1", "easy"], ["title2", "hard"], ["title3", "medium"] ]
    }
});

The code I have right now is this:

function setFilters() { 
    var options = {};   

    for (var facet in facets) {
        for (var facetKey in facets[facet]) {
            if (!filterExists(facetKey)) {
                options[facetKey] = new Array(new Array(facets[facet][facetKey], "equals"));
            }
            else {
                (filters[facetKey]).push(new Array(facets[facet][facetKey], "equals"));
            }
        }
    }

    filters.set(options);
}

The function filterExists simply checks if the key "title" is present in the model. When I run this, it says that filters[facetKey] is undefined. But isn't this the first-level array I need to push my element into?

4
  • 1
    Offtopic: instead of new Array(new Array(facets[facet][facetKey], "equals")) why not you write the much shorter [[ facets[facet][facetKey], "equals"]]? Is filters a global variable? filters or Filters? Commented Feb 20, 2012 at 17:22
  • @biziclop yes, filters is a global variable. Thanks for the tip on the arrays. Commented Feb 20, 2012 at 17:24
  • Also { {"title1", "easy"}, {"title2", "hard"} } should be [ ["title1", "easy"], ["title2", "hard"] ]. {} is for creating objects: { name:'Joe', city:'London' } Commented Feb 20, 2012 at 17:32
  • @biziclop, yes I'll change that now to prevent confusion in the future. Commented Feb 20, 2012 at 18:56

1 Answer 1

7

You can access model attributes with .get() and .set() functions, or directly via the .attributes property:

http://documentcloud.github.com/backbone/#Model-attributes

var filters = new Filters();
filters.attributes.facetKey.push( [...] );

OR

filters.set('facetKey', ( filters.get('facetKey') || []).concat([...]));

Anyway, here is your transformed function which may or may not work:

function setFilters() { 
    for (var facet in facets) {
        for (var facetKey in facets[facet]) {
            var f = [ facets[facet][facetKey], "equals" ];

            if( filterExists(facetKey)) {
            // OR: if( filters.attributes[ facetKey ]){
                filters.attributes[ facetKey ].push( f );
            }else{
                filters.attributes[ facetKey ] = [ f ];
            }
        }
    }

    // trigger change event for all attributes
    filters.set( filters.attributes );
}

Bonus:

(filters.attributes[ facetKey ] = filters.attributes[ facetKey ] || [] ).push(f);
Sign up to request clarification or add additional context in comments.

8 Comments

but will this trigger a change event?
Only using .set() would trigger any events, directly accessing an object's property can't trigger anything (unless setters are somehow involved).
I think this is a good answer, since it accomplishes what the @kaspnord was asking, but since 'event' triggering does not automatically occur it could cause problems. For example if there are views waiting for changes to re-render themselves, etc. Maybe you should manually trigger the event after adding the element?
Thanks guys, this works! Looks like I was treating the models object as an array, which was why I couldn't access it. Also, thanks for the alternative to 'filterExists'... it's much better :)
filters.set('facetKey', filters.get('facetKey').push(...)); // BackBone 0.9 FTW will not work because array.push() returns the length of the array not the array itself. you have to separate that out
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.