This project is read-only.

Bindings

Binding in Lava is the synchronization between a logical object or property to a visual element. It allows us to automatically update the UI, or View, whenever an object or property changes in code. Think of the Person.first property being bound to the innerText of a label. In Lava, we can also create bindings that go the other way, from the UI to the object or property. A good example of this would be an text input that is bound to the Person.first property.

This is a simple example of the most basic binding:

var Person = Lava.Object({
    first: 'John',
    last: 'Doe',
    fullName: Lava.Computed('first,last', function () {
        return this.first + ' ' + this.last;
    }),
    badgeColor: 'blue'
});

Lava.bind({ object: Person });

Notice the line Lava.bind({ object: Person });. This method takes care of binding the object (Person) to the view, which, in this case, is the body of the document because no selector was specified.

This is all that is required to complete the binding on the UI side:

<h1 data-lava-bind="{innerText: first}"></h1>

Here is a slightly more complex example of binding to the Person object:

<h1 data-lava-bind="{innerText: fullName, style.color: badgeColor}"></h1>

As you may have posited, the ui will automatically change when the bound property changes.

Binding events to functions works in a similar way. Let's add a function to the Person object that will alert the user when a button is pressed.

var Person = Lava.Object({
    first: 'John',
    last: 'Doe',
    fullName: Lava.Computed('first,last', function () {
        return this.first + ' ' + this.last;
    }),
    badgeColor: 'blue',
    alertUser: function () {
        alert('You clicked the button');
    }
});
<input type="button" data-lava-bind="{click: alertUser}" value="click me!" />

You can also bind the result of a function to a property in Lava. The syntax for this is similar to a normal property binding except for the fact that we need to have parenthesis at the end of the property in the binding. Let's look at a simple example.

var Sample = Lava.Object({
    text: function () {
        return 'Date: ' + new Date();
    }
});
<h1 data-lava-bind="{innerText: text()}"></h1>

Collection Binding

In the scenario where you want to bind a collection of objects to the UI, Lava includes a special tag to do this. The syntax is a bit different when binding to a collection. In this example we set up a collection and then bind it to a list.

var Car = Lava.Object({
    make: null,
    model: null,
    color: null
});

var CarController = Lava.Object({
    cars: Lava.Collection.of(Car),
    edit: function () {
        //...
    }
});

// add some cars
CarController.cars.add(Car.create({ make: 'Toyota', model: 'Corolla', 'Gray' }));
CarController.cars.add(Car.create({ make: 'Ford', model: 'Mustang', 'Red' }));
CarController.cars.add(Car.create({ make: 'Honda', model: 'Civic', 'Black' }));

Lava.bind({ object: CarController });

<ul>
    <lava:for data-lava-ex="$car in cars">
        <li>
            <span data-lava-bind="{innerText: $car.make}"></span><br>
            <span data-lava-bind="{innerText: $car.model}"></span><br>
            <span data-lava-bind="{innerText: $car.color}"></span><br>
            <button data-lava-bind="{click: /CarController.edit}">edit</button>
        </li>
        <hr>
    </lava:for>
</ul>

Notice that the binding expressions are a bit different. For the collection, the binding expression is written as data-lava-ex="$<iterator label> in <collection property name>". The binding expression within the for tags must be written as data-lava-bind="{<attribute/event/special>: $<iterator label>.<property name>}". If you need to access a property on an object that is outside of scope you must use an absolute path, written as /<root object>.<child object/property>.<...>. Here is an expanded version of the example above to illustrate this.


Two-Way Binding

As you have seen above, Lava allows for rich binding of your data to the UI so that you can separate these two aspects of your application and not have to worry about glue logic. So what if you want a bound element such as a text input to send a changed value back to the model? Simple, you apply a two-way data binding like so:

var Person = Lava.Object({
    first: 'John',
    last: 'Doe'
});

Lava.bind({ object: Person });

<input type="text" data-lava-bind="{value: first, mode: twoWay}" />

This is all you need for a two-way data binding!

String Formatting

Lava allows you to format the bound value by applying the value to a format string. You accomplish this through the format property in a binding expression.

var Test = Lava.Object({
    name: 'Terry Phillips'
});

<h2 data-lava-bind="{innerText: {bind: name, format: 'Hello {0}'}}"></h2>

The formatExclusive property allow you to suppress the binding if the bound property is null or a blank string.

var Test = Lava.Object({
    name: ''
});

<h2 data-lava-bind="{innerText: {bind: name, formatExclusive: 'Hello {0}'}}"></h2>

This binding will not display the formatted string in this case because the name property is blank.

Last edited Mar 13, 2013 at 5:51 AM by tjscience, version 10

Comments

No comments yet.