Data-binding Made Easy with Alloy: Part 2

7 Flares 7 Flares ×

In the first part of this series, we looked at using the Titanium Alloy MVC framework, with its built-in Backbone.js data-binding, to easily bind data to Views with minimal code.

(This post assumes you’ve followed along with Part 1 which was using a mock library to generate models and collections — things are a little different if you use the “stock” Alloy Model definitions — I’ll cover the benefits and differences of both in Part 3)

That’s great for lists, but what about “detail” views — where you’d like to show a single instance of a model in a view / controller?

Traditionally in Titanium, you might do something like this:

Alloy.createController("detailView", data).getView().open();

where data is either the value or object you want to pass across, then in the detailView controller you might do the following (assuming data contained an object with properties):

$.firstName.value = args.firstName;
$.lastName.value = args.lastName;

This is fine of course, but it requires you to bind the data manually in the controller to every element in the view – and that means writing more JavaScript.

Alloy provides a much simpler way of doing this by passing across a model itself and then binding using the built-in data-binding of Alloy itself, meaning little or no JavaScript is required.

To use this you use a special $model parameter when passing the data to the controller. So, for example, if you’d obtained a model from a TableView with:

function onClick(e) {
	Alloy.createController("detailView",{
		$model: Alloy.Collections.contacts.at(e.index)
	}).getView().open();
}

Depending on how you’ve created your models and controllers (for example if you’ve created them outside of the normal model definitions folder), you may need to do a .transform() on the model before passing it to the controller.

In this case, you would do the following:

function onClick(e) {
	var model = Alloy.Collections.contacts.at(e.index);
	model.transform();
	Alloy.createController("detailView",{
		$model: model
	}).getView().open();
}

In this example, a transform method is being called against the model — this basically does a toJSON() on the model and exposes the data in the _transform property.

If your models support / have a transform function, that’s all you need to do — if not, you would need to manually add this so that it created the JSON property for you.

With this in place, the detail view itself just has to contain standard XML that maps the model properties to the view:

<Window>
    <View layout="vertical">
        <View>
            <Label class="caption">First Name</Label>
            <TextField value="{firstName}"/>
        </View>
        <View>
            <Label class="caption">Last Name</Label>
            <TextField value="{lastName}"/>
        </View>
    </View>
</Window>

The above example is indicative — some styling has been omitted.

If you do want access to the model itself in the controller code, you can do that by referencing:

var firstName = $model.toJSON().firstName;

Simple as that — data binding in detail views made easy with Alloy.

For more guides check out Alloy Data Binding and the backbone.js documentation, and please leave a comment!

7 Flares Twitter 0 Facebook 0 Google+ 0 LinkedIn 7 Email -- 7 Flares ×

10 Comments

  1. darknos

    There is a more backbone way to get a property value:

    var firstName = $.model.get(“firstName”);

    but in case you need the same value you have in TextField you should take:

    var firstName = $.model. _transform.firstName;
    //or
    var firstName = $.model. transform().firstName;

    • Jason Kneen

      Thanks for the comment.

      Yep that’s a valid way of accessing model properties, but using it here defeats the object of this piece, which is to show how you can eliminate the need for binding JavaScript in the controller, unless you need to update the data.

      The example above shows how this can be done using the $model property and *only* adding tokens to the XML view which will automatically rebind the data to the view if the model changes (if using the Alloy model tag) — manually binding won’t.

      Also not sure $.model is valid in this case as no model has been attached to the view in the XML.

      • darknos

        Yeah… I misstype $.model. It should be $model.

  2. marcin

    this method won’t update the label text property when the model is updated, right?

    • Jason Kneen

      If you’re talking about setting the label manually in the controller, correct. If you bind it with the {firstName} in the XML it’ll be updated when the model changes.

      • darknos

        No. In case you passed $model to controller – view will not update on model change. Alloy will not generate any “onchange” code for $model. Only generate code like this:

        $.__views.__alloyId6 = Ti.UI.createTextField({
        value: $model.__transform.lastName,
        id: “__alloyId6”
        });

        If you want to change view on model change you have to define tag

        • Jason Kneen

          If you’re using Alloy Models and Collections (defined in the models folder) and use the model tag then the binding will happen and changes will be refreshed. You cannot do any auto-refreshing of the view by using .set — it won’t work.

    • darknos

      Right. It will not update label on model change. using $model will not produce onchange code in controller.

  3. I prepared two samples of DataBinding for sigle model instance.

    https://github.com/darknos/AlloyDataBindingSample

    Details controller use described above “$model” way. and you can see that $model.set(“lastName”, “Other name”) will not change text field on screen.

    DetailsWitchChange controller pass only index and use Model tag in XML and reflect on model changes.

    Jason, I guess, we need Alloy Data Binding Part III

    • Jason Kneen

      If you use the normal model / collection definitions in Alloy, and use the tag then the view should update. If you use the approach of doing .set to manually bind then it will not update automatically. Will follow up in a Part 3

Comments are closed.

computer and tablet showing Appcelerator software
Start free, grow from there.
7 Flares Twitter 0 Facebook 0 Google+ 0 LinkedIn 7 Email -- 7 Flares ×