Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone / Underscore chain method with where method

There has to be something simple I am missing here.

http://jsfiddle.net/v9mdZ/

I am just learning Backbone and Underscore/loDash and am trying to get familiar with chain.

I have the following code, which works as expected:

var ids = _.pluck(collection.where({'is_checked':true}), 'id');

I attempted to refactor this, using chain like so:

var ids = collection.chain().where({'is_checked':true}).pluck('id').value();

Why doesn't the refactored code work? Am I using chain wrong?

Solution (details below)

Don't use where with chain.

like image 764
Bart Avatar asked Oct 26 '12 16:10

Bart


People also ask

What is Backbone used for?

Backbone is known for being lightweight, as its only hard dependency is on one JavaScript library, Underscore. js, plus jQuery for use of the full library. It is designed for developing single-page web applications, and for keeping various parts of web applications (e.g. multiple clients and the server) synchronized.

How Backbone js works?

BackboneJS provides various building blocks such as models, views, events, routers and collections for assembling the client side web applications. When a model changes, it automatically updates the HTML of your application. BackboneJS is a simple library that helps in separating business and user interface logic.

What is El property of backbone JS view?

The Backbone. js View el method defines the element that is used as the view reference. this. el is created from the view's tagName, className, id and attributes properties, if specified.


1 Answers

The merging of some Underscore methods into collections is a little imperfect. When you say collection.some_mixed_in_underscore_method(), the collection unwraps some of the Backbone stuff behind your back so that the Underscore method is applied to the attributes inside the collection's models; it sort of works like this:

var ary = _(this.models).map(function(m) { return m.attributes });
return _(ary).some_mixed_in_underscore_method();

But collection.chain() doesn't work like that, chain just wraps the collection's models directly so if you do this:

console.log(collection.chain());

you'll see that chain is giving you an object that wraps an array of models. Your models won't have an is_checked property (i.e. there is no model.is_checked), they will have is_checked attributes though (i.e. there will be model.get('is_checked') and model.attributes.is_checked).

Now we can see where everything goes wrong:

collection.chain().where({'is_checked':true})

The models don't have is_checked properties. In particular, there won't be any models where is_checked is true and everything after the where is working with an empty array.

Now that we know where things go sideways, how do we fix it? Well, you could use filter instead of where so that you can easily unpack the models:

collection.chain()
          .filter(function(m) { return m.get('is_checked') })
          .pluck('id')
          .value();

But, your models don't have ids yet as you didn't create them with ids and you haven't talked to a server to get ids so you're going to get an array of undefineds back. If you add some ids:

var collection = new App.OptionCollection([
    {id: 1, 'is_checked': true},
    {id: 2, 'is_checked': true},
    {id: 3, 'is_checked': false}
]);

then you'll get the [1,2] that you're looking for.

Demo: http://jsfiddle.net/ambiguous/kRmaD/

like image 58
mu is too short Avatar answered Nov 05 '22 23:11

mu is too short