by

Bind existing model

One of the great things the Alloy-framework introduced was data-binding. This feature is improving with every release, but still has some issues. One of them was shown in this gist by Timan Rebel the other day. It displays how only new, empty model instances can be created and bound to by the <Model /> element. There is no way to load and bind an existing model that way.

I’ve forked Timan’s gist to show a simple workaround. To know how it works, you need to understand the different types of behavior triggered on Alloy by different ways of mapping using curly brackets:

  • <Label text="{$.user.name}" /> requires <Model id="user" src="user" />, which creates a new and empty model to which it will bind.
  • <Label text="{name}" />, meant for binding to collections and into required views, could be used as a workaround. It will look for a $model argument passed to the controller, which could be the existing model. This requires a few tricks however. The passed $model is expected to have a *Object* __transform property. Also, Alloy correctly gets the data from the model when the views are created, but does not listen to later changes. So you would need to add a listener for that yourself. See this gist.
  • <Label text="user.name" /> (note the missing $.) is the one we will use. It will correctly bind to a singleton Model named user, that we will create in the opening controller.

Please note that this will only work for a single concurrent instance of the model class. A JIRA ticket was opened to provide a solution for multiple concurrent instances.

Profile view

In the view I removed the <Model /> element, since I know the singleton will be there because I declare it in the index view. I replaced {$.user.name} by {someUser.name} to make it refer to the singleton instead of the local instance:

Compared to original:

Profile controller

The profile controller does not require any code anymore and is just how we want it to be – empty:

Compared to original:

Note: args.user instead of args.user.attributes works as well.

Index view

The <Model /> has been moved to the index view, which will further just contain a button to open the profile window:

Index controller

The index controller now uses the singleton model declared in the view instead of a local instance. I’ve added an interval to show how the profile view updates correctly:

Compared to original: