It is very apparent that in order to “get” SproutCore you have to understand a bunch of fundamental concepts, such as how key-value observing (KVO) and bindings work. For someone like myself, I need to work on the fundamentals and have it both verbally and visually explained. For example, one of the most basic concepts seems to be binding a view’s properties with some model object’s properties. Seems trivial enough. However, I kept getting confused how to really connect a view with a model. the examples I would see online always showed something like for view V that has a property called “value” and a model object M that has a property called “value”, you would hook the two together as so:
valueBinding: 'myApp.SomeController.value'
Where the above wiring happens when you create an instance of the view V. I kept asking myself, well what happens if the model object doesn’t have a property named “value”? Then what? What if you want to make a generic view that doesn’t know anything about the properties of some given model? How then to do you bind/wire/hook the two together? Turns out with SproutCore’s bindings the name of the properties doesn’t matter, which is when I got the “a-ha!” moment.
So let’s say I have a view called MyView with two properties, name and description. On the other side, I have two model objects. The first model object is a User object with properties fullname and title. The second model object is a Project object with properties title and description. So to wire the view with the User object we get the following:
nameBinding: 'myApp.userController.fullname'
descriptionBinding: 'myApp.userController.title'
And to bind the view with the Project object we get the following:
nameBinding: 'myApp.projController.title'
descriptionBinding: 'myApp.projController.description'
So based on the above two examples, it becomes clear that the view’s properties and the model’s properties do not have to be called the same thing. Hazzuh! Although if the properties do happen to be called the same thing then that’s fine too. In fact, the example extends to all bindings in general.
Now, the code examples above do raise some other questions. First, you may notice there’s no reference to User object or a Project object. Rather, the bindings seem to be using these controller thingies called “userController” and “projController”. Turns out that it is good practice to not allow views to directly connect to a model object, but, rather, that the view connects to a controller object that acts as a proxy to the model object. The controller decouples the view and the model object. Okay, cool. So you have to create these controller objects. No sweat.
The other thing that may seem weird in the binding examples is the string that looks like some kind of path, such as ‘myApp.userController.fullname’. This is called a property path. SproutCore has this handy feature of looking at an object graph and traversing it to get to a object’s given property. The path can be either relative or absolute. In this case, the example shows an absolute path where the ‘myApp’ object is the root of the graph. Cool. Makes coding easier.
Finally, what’s the deal with the xxxBinding, where the “Binding” is a suffix to the property named “xxx”? When creating a new instance of a view, there is logic that will check for these specially named properties that get added to the view. When found, SproutCore will then auto-magically create the real binding mechanisms that connects the view’s property xxx with the model’s property… er, in this case the controller’s property acting as a proxy to the underlying model.
Anyway, this helped clear up some of the confusion I had. I’ve included a picture to show visually what is going on.

When is the model associated to the controller ? is it done automatically using the name as a convention, is default a userController associated to a user model
I had to go back over this post. It’s been a while since I wrote and posted it :-).
There are two ways in which a common object controller (SC.ObjectController) can be assigned an object to proxy against — and not just a model object that extends from SC.Record.
The first approach is that your application, in one form or another, explicitly sets the controller’s content property. (A controller proxy’s any object that is set to the content property). As an example:
MyApp.User = SC.Record.extend({ … });
var user = MyApp.get(‘store’).find(MyApp.User, “123″);
MyApp.userController.set(‘content’, user);
The second approach is to use bindings so that your object controller is bound to some other controller’s property. That seems weird when you first read it. Why would you want to bind a controller to another controller? One common scenario is that you have an array controller that proxies an array of content, such as an array of user objects. A person selects a specific user in a list view and you want your userController to get that selected user. You’d do something like the following:
MyApp.usersController = SC.ArrayController.create({ … });
MyApp.userController = SC.ObjectController.create({
contentBinding: ‘MyApp.usersController*selection.firstObject’
contentBindingDefault: SC.Binding.oneWay();
});
What you are seeing above is something based on the root controller paradigm. In this case, the MyApp.usersController is the root controller that starts to feed data through a series of controllers and then on to views that are all connected through bindings. For the MyApp.usersController, in this example, it would be explicitly assigned an array of user objects.
In both cases you’re assigning the controller’s content property a value, but just under different scenarios. In a typical SC app, you’ll end up using a combination of both approaches in order to feed data throughout your application.
Great article and the site overall is a great resource for sproutcore! I just wish I could have found this sooner why not contribute this to the sproutcore wiki? Or at least provide a link there?
Anyways, this article really solidified my understanding of how bindings work in views, but I’ve been tripped up on something for two days and it seems like it should be pretty minor but I can’t seem to figure it out:
How do I output these properties to the screen?
The only way I know so far (I’m new) is to use the very limited valueBinding property, which basically hijacks all output for the view and just echos the property’s value. What would make more sense is if I could use it in conjunction with the render function, then I could output as many of these properties as I want within the same view. But the render function seems to have no access to bound properties on the view, even though it has full access to any other properties. Could you explain exactly how I would go about outputting these properties in the view?
Thanks!!
I saw your post on the SproutCore group. Be sure to check out my response at:
http://groups.google.com/group/sproutcore/browse_thread/thread/6e660ca0a252134e
See the snipped version of the thread below.
————–
<snip/>
Thanks Mike I really appreciate your response, however I still
couldn’t get it to work, can you please review my code? Thanks!!
favoritesCountView: SC.LabelView.design({ favCount: null, favCountBinding: 'MyApp.favoriteListingCollectionController.length', click: function() { alert(this.favCount); }, render: function(context, firstTime) { var total = this.get('favCount'); context = context.push("<div>My Favorites (" + total + ")</div>"); sc_super(); } })<snip/>
A few things:
1) Be sure to clear your SproutCore project’s tmp directory since it might not include all files the you added to your app, such as a controller.
2) In order to for the render method to be automatically invoked
whenever favCount is changed, you need to set the displayProperties property on the view, like so:
Out of curiosity, why are you overriding the label view’s render
method just to display the total based on what has been assigned to favCount? You should not have to touch the render method for cases like this. Instead you should use a binding transform against the view’s value property. Example:
favoritesCountView: SC.LabelView.design({ valueBinding: SC.Binding.transform(function(value) { return "My Favorites (%@)".fmt(value); }).oneWay('MyApp.favoriteListingCollectionController.length') })Let bindings help you do the work of transforming data. The binding transform provides a value from the favoriteListingCollectionController’s length property and then returns a string with the value injected using the fmt() method.