Bindings Unleashed

by Evin

Bindings are one of the most important aspects of Sproutcore. Bindings give us the ability to do complex UI interactions with very little code. They have turned tedious and error-prone code to update the interface a thing of the past. It now becomes a simple setup and configuration task to wire up things to be automatically updated. They are incredibly powerful, but can be easily confusing and misused.

the basics

Bindings are just configuration that one sets up so that when a value changes it changes all the elements that are connected to it. They are found most often in the view layer, but are used heavily in the controller and the model as well. We will focus on the view layer. Here is a simple picture of what bindings do for you:
Bindings-Views

The general concept is that all the views connect to one value ‘name’ in the controller so that if it changes at any time it is reflected automatically in the views. This is the power of bindings.

the basic rules for bindings

There are a few simples rules to follow when using bindings in sproutcore. If you follow these, you will have a much better understanding of what is occurring and will make code debugging much easier. Often times if your model and controller layers are set up correctly, most of your bugs will ben in your bindings.

Rule #1: Use the ‘-Binding’ naming convention ONLY for a bindings

When you set up a binding you uses the following convention:

  // DO THIS 
  nameBinding: 'myApp.modelController.name',
  // NOT THESE
  skiBinding: 'Rossignol'
  glueBinding: 'Very Firm'

Often you might want to pass bindings through a view to another view. DO NOT use the ‘-Binding’ convention! Think of anything with the postfix of ‘-Binding’ as a reserved word. This will set up a real binding that will update whenever something changes it will update. This will slow your app down as things are being updated without the need.

Rule #2: Use the ‘-Path’ naming convention to pass a binding to another view

If you do need to pass a binding to a child view or pass it around for some reason, use the ‘-Path’ naming convention:

  namePath: 'myApp.modelController.name'

A further discussion of using this convention can be found in the discussion about composite views.

Rule #3: View Bindings must only be set up in the ‘.lproj’ layer

Fight the urge to set up bindings for the view layer anywhere but in the ‘.lproj’ layer. You should never be directly setting bindings in a view class even if you know what something is supposed to be. This is a maintenance nightmare and will cause lots of problems if you ever have to change something. It also violates some of the basic OO design structure. If you need a bind set up further down, use the ‘-Path’ naming convention.

Rule #4: Use One Way Bindings whenever possible

Always use a One Way Binding when you can. This will speedup performance because the SC RunLoop won’t have to do extra work to update values and observe values on both ends. Example:

  nameBinding: SC.Binding.from('myApp.modelController.name').oneWay()

This is particularly useful when you are creating views that are for display purposes only. There is no need to have any changes to the view be observed for change.

Using Bindings in Sproutcore

When you set up bindings you are actually setting up a binding pattern that is created at run time in the init() method. This is why it is very important to add the sc_super() to the top of your init() if you ever overwrite it.

The ‘*’ Trek Convention

Often times you will see a ‘*’ being used in some bindings in sproutcore. This little feature is one of the massive improvements that sproutcore has made to Binding from Cocoa. The ‘*’ creates a chained observation structure that is very powerful and causes less code to have to be created.

The ‘*’ creates the observation point in the binding observation chain. Everything to the left of the ‘*’ is the object that is to be observed and everything to the right of the ‘*’ is the property chain that is being observed for changes. Example:

  nameBinding: 'myApp.modelController*otherProperty.name'

An english reading of this would be: “Observe ‘myApp.modelController’ for changes to the property ‘otherProperty.name’”. This means that any change to ‘otherProperty’ or ‘otherProperty.name’ will trigger a binding update. This is particularly useful when you want to observe an array for changes to the whole thing or to the size of the array.

You never want to add a ‘*’ to the last property it is already implied:

  nameBinding: 'myApp.modelController.name'
  // Same as...
  nameBinding: 'myApp.modelController*name'

Absolute and Relative Paths

Most of the time you will be using an absolute path for setting up your bindings. This is the most common form that you will use. Often you might want to make a relative path for a binding. This will be used when you want to bind a child view to a parent view in a view class. You can still use the ‘*’ naming convention. Here is an example of a relative path:

  nameBinding: '.parentView.name'
  descriptionBinding: '.parentView*otherObject.name'

Setting up bindings implicitly

There are a few times where you might want to set up binding explicitly. The best to use the .bind() method on SC.Object:

  this.bind('name', SC.Binding.from('myApp.modelController.name').oneWay());

You will want to use this rarely and only when you want to do some dynamic binding that can change or morph. For the general uses, you want to avoid using this at all costs, but it is good to know for future references.

conclusion

Bindings are incredibly powerful and are the base of what makes Sproutcore so cool. In a later post we will talk about how to use bindings to your advantage in the controller layer with the Root Controller methodology.

This entry was posted on Saturday, June 20th, 2009 at 4:45 am and is filed under Best Practices, Coding Tutorials, Sproutcore. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

One Response to “Bindings Unleashed”

  1. It’s Got What Plants Crave » Blog Archive » Composite Views Says:

    [...] my last post on bindings, I talked about Rule #2 (The ‘-Path’ Convention) which started a bit of buzz on when [...]

Leave a Reply