Search code examples
sproutcore

SproutCore Confusing in Binding ListView Content to ArrayController


In SproutCore, it is a common way to bind the ListView.content to an ArrayController:

Todos.todosController = SC.ArrayController.create({
});

SC.ListView.design({
    contentBinding: SC.Binding.oneWay('Todos.todosController'),
    exampleView: SC.CheckboxView.design({
      ..........
    })
})

But the "content" field of ListView which extends from SC.CollectionView is SC.Array, should't it be:

contentBinding: SC.Binding.oneWay('Todos.todosController.content')

Any explanation will be appreciated. Sorry for the poor english.

@TopherFangio I looked at the implementation of SC.ArrayController and find out that .arrangedObjects is a very simple computed property that returns the object it belongs to:

arrangedObjects: function() {
    return this;
}.property().cacheable()

So binding to .arrangeObjects is actually the same as binding to: App.arrayController.arrangeObjects

I also find out SC.ArrayController extends SC.Array and implements the two required methods 'replace()' and 'objectAt()'.

To support SC.Array in your own class, you must override two primitives to use it: replace() and objectAt().

The implementation of these two methods in SC.ArrayController will do some array controller specific check and forward the request to the .content property.

So just like @TopherFangio said, SC.ArrayController is a proxy for it's underlying .content property. If i bind to App.arrayController.content directly rather than the controller itself, i think i will lose all the arrayController goodness.

Thanks again for your great help @TopherFangio.


Solution

  • SC.ArrayController is actually a proxy object which does some nice things for you.

    You can certainly bind to the .content property, but you could also bind to the .arrangedObjects property and set the orderBy property. This would let you modify orderBy and have the bound list automatically update. In general, this is what you want to do.

    Additionally, I believe that Todos.todosController.length will always be a number, even if the content is null. In contrast, calling Todos.todosController.content.length would throw an error if content was null.

    Hope this helps :-)