Skip to content

Commit

Permalink
Merge pull request NativeScript#53 from NativeScript/boevski/beta-rel…
Browse files Browse the repository at this point in the history
…ease

Boevski/beta release
  • Loading branch information
boevski committed Mar 4, 2015
2 parents 5490e92 + e423cba commit 0d58591
Show file tree
Hide file tree
Showing 6 changed files with 334 additions and 195 deletions.
80 changes: 44 additions & 36 deletions bindings.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
---
nav-title: "NativeScript Data Binding"
nav-title: Data Binding in NativeScript
title: "App: Data Binding"
description: "NativeScript Documentation: Data Binding"
description: How to bind a data source to a GUI control.
position: 8
---

#Data Binding
# Data Binding

##Overview
## Overview

Data binding is the process of connecting application user interface (UI) to a data object (business model). With a correct data binding settings and if data object provides proper notifications then when data changes application UI will reflect changes accordingly (source to target). Depending on settings and requirements there is a possibility to update data from UI to data object (target to source).
Data binding is the process of connecting an application User Interface (UI) to a data object (business model). With the correct data binding settings in place and if the data object provides proper notifications, then when the data changes the application UI will reflect the changes accordingly (source to target). Depending on settings and requirements there is a possibility to update data from UI to data object (target to source).

> **source** is used as any business logic object, and **target** as any UI control (like TextField).
> In this article, the term **source** is used to mean any business logic object and **target** to mean any UI control (such as TextField).
##Basic data binding concepts
## Basic Data Binding Concepts

Generally almost every UI control (since all controls are created with data binding in mind) could be bound to a data object. However there are few restrictions for data binding to work out of the box.
Every UI control could be bound to a data object because all controls are created with data binding in mind. There are, however, a few restrictions for data binding to work out of the box:

* Target object should be a successor of **Bindable** class.
* Target property should be a **dependency property** in order to use data binding from target to source (or two way data binding). A plain property could be used if there is no need of **twoWay** binding.
* Data (business) object should raise **propertyChange** event for every change in the value of the property.
* The target object must be a successor of class **Bindable**.
* The target property must be a **dependency property** in order to use a target-to-source data binding, or a two-way data binding. You can use a plain property if you don't need a two-way binding.
* The data object must raise a **propertyChange** event for every change in the property value.

##Direction of data flow
## Direction of Data Flow

Part of the data binding settings is the way data (values) flows. NativeScript data binding supports following data transmissions.
An important part of setting up a data binding is determining the way data flows. The NativeScript data binding supports these data transmissions types:

* **OneWay** - this is a setting that indicates that a change in the source object will update target property, but a change in target property will not be propagated back to source (data object). Any update to the target property (except binding) will stop the binding connection. - this is the **default** option.
* **OneWay**—This setting indicates that a change in the source object will update the target property, but a change in the target property will not be propagated back to the source. Any update to the target property (except binding) will break the binding connection. This is the **default** setting.

* **TwoWay** - this setting indicates that both changes in source object will be reflected to the target and changes from target will update the source object. Very useful in cases when user input should be handled (for example user writes a text - text is written within a TextField control and is updated to a underlying data property of the source object).
In order to use this option binding options should set **twoWay as true**. Following examples show how to do that.
* **TwoWay**—This setting indicates that both changes in source object will reflect in the target and changes in the target will update the source object. It is very useful in case you need to handle user input (for example the user enters texts in a `TextField` control which updates an underlying data property of the source object).

##Creating a binding
## Creating a Binding

* Creating binding in code.
You have two approaches to creating a binding: in code or in XML. These are explained below.

1. In order to create a working binding first we should have a source object. Source object should raise **propertyChange** event for every change of any property. NativeScript has a built-in class that fulfills that requirement (Observable). Following is a code snippet that creates an observable object instance.
### Creating a Data Binding in App Code

1. Create a source object that raises a `propertyChange` event for every change in any of its properties. NativeScript provides a built-in class `Observable` that does just that. The following code example creates an observable object instance:

``` JavaScript
var observableModule = require("data/observable");
Expand All @@ -45,7 +46,7 @@ In order to use this option binding options should set **twoWay as true**. Follo
var source = new observableModule.Observable();
```

2. Creating a target object. For the sake of example we will also create a target object an instance of Bindable class (all UI controls derives from it).
2. Create a target object. In the following example we create a target object as an instance of the `Bindable` class (from which all UI controls derive).

``` JavaScript
var textFieldModule = require("ui/text-field");
Expand All @@ -56,7 +57,7 @@ In order to use this option binding options should set **twoWay as true**. Follo
var targetTextField = new textFieldModule.TextField();
```

3. Create a data binding.
3. Finally, create the data binding:

``` JavaScript
var bindingOptions = {
Expand All @@ -76,7 +77,7 @@ In order to use this option binding options should set **twoWay as true**. Follo
targetTextField.bind(bindingOptions, source);
source.set("textSource", "Text set via binding");
```
This example will update **targetTextField.text** property with a *"Text set via binding"* value, **twoWay** option ensures that every change of the **targetTextField.text** property (via user input) will be stored within **source.text** property. The new value of the text property could be get via:
The above updates the `targetTextField.text` property with the *"Text set via binding"* value. The `twoWay` option ensures that every change in the `targetTextField.text` property (resulting from user input) will be stored within the `source.text` property. You can get the new value of the text property using this clause:

``` JavaScript
source.get("textSource");
Expand All @@ -85,11 +86,11 @@ This example will update **targetTextField.text** property with a *"Text set via
source.get("textSource");
```

* Create a data binding in xml
### Creating a Data Binding in XML

1. Create a source object. "source" object from the previous case (creating binding with code) will be used for following examples.
1. Create a source object as described in [Creating a Data Binding in App Code](#creating-a-data-binding-in-app-code).

2. Describe a binding within xml (using a mustache syntax).
2. Describe the binding in XML using Mustache:

``` XML
<Page>
Expand All @@ -99,13 +100,17 @@ This example will update **targetTextField.text** property with a *"Text set via
</Page>
```

> Note: For an UI elements created with an xml declaration when data binding is set **twoWay** option is **true** by default.
> When you set a data binding for an UI element declared in XML, the `twoWay` option is set to *true* by default. You don't need to set it explicitly.
When using an XML declaration you only set property names for the target (`text`) and the source (`textSource`). Specifying a source for the binding is done on a later stage (the so called late binding). Read on to learn how to set the source.

## Specifying a Binding Source

With an xml declaration we set only properties names both for target (text) and source (textSource). The interesting thing here is that there is no source of the binding (actually it is not set directly).
Data binding in NativeScript works with any object that emits a `propertyChange` event. When creating a binding object, the source can be set as the second parameter of `bind(bindingOptions, source)` or can be omitted.

##Binding source
In case it is omitted, a special property named `bindingContext` of the `Bindable` class is used as a source. This property is inheritable across the visual tree. This means that a control can use as source the `bindingContext` of the first **parent** element in which `bindingContext` is explicitly set.

The important part of the data binding is setting the source object. NativeScript data binding works with any object that emits a **propertyChange** event. On the process of creating binding source can be set as second parameter of the bind(bindingOptions, source) or could be omitted. In that case for source is used a special property named **bindingContext** of the Bindable class. The special about this property is that it is inheritable across the visual tree. This means that control can use the **bindingContext** (as source) of the first **parent** element with a explicitly set **bindingContext**. With the previous example **bindingContext** can be set either on Page instance or StackLayout instance and TextField will have a proper source for its "text" property binding.
In the previous example, `bindingContext` can be set either on the Page instance or the `StackLayout` instance and `TextField` will still have a proper source for its `text` property binding.

``` JavaScript
page.bindingContext = source;
Expand All @@ -118,9 +123,10 @@ page.bindingContext = source;
stackLayout.bindingContext = source;
```

* Create a data binding to an event in xml
### Create a Data Binding to an Event in XML

When using an XML declaration, you can bind a function to execute on a specific event (MVVM command-like). You do this by setting the source property value to an event handler function as follows:

There is an option to bind a function to execute on a specific event (MVVM command like). This option is available only through an xml declaration. The different part is that the source property should have an event handler function as value.

``` JavaScript
page.bindingContext = source;
Expand All @@ -135,7 +141,7 @@ source.set("onTap", function(eventData) {
});
```

and how xml will look like:
This is what the XML declaration looks like:

``` XML
<Page>
Expand All @@ -145,16 +151,18 @@ and how xml will look like:
</Page>
```

> Note: Be aware that if there is an event handler function **onTap** within the page code behind ([more info about xml declarations](./ui-with-xml.md)), and **onTap** function within the **bindingContext** object then there will be 2 event handlers hooked for that button and both will be executed on tap event.
> Be aware that if there is an event handler function `onTap` within the page code behind ([more info about XML declarations](./ui-with-xml.md)) *and* an `onTap` function within the `bindingContext` object, then you get two event handlers hooked to that button, both of which are executed on tap event.
## Unbinding

##Stop binding
Under normal circumstances you don't need to unbind from a data object, because the Binding object uses weak references which prevents memory leaks. However there are business cases where you may need to perform unbinding.

Generally there is no need to stop binding explicitly, since Binding object uses weak references which prevents any memory leaks. However there are some scenarios (business logic) where binding must be stopped. In order to stop existing data binding just call **unbind** method with target property name as argument.
To break a binding, call the `unbind` method with the target property name as argument.

``` JavaScript
targetTextField.unbind("text");
```
``` TypeScript
targetTextField.unbind("text");
```
More information about binding can be found in [API-Ref](./ApiReference/ui/core/bindable/Bindable.md).
More information about binding can be found in the [API Reference](./ApiReference/ui/core/bindable/Bindable.md).
Loading

0 comments on commit 0d58591

Please sign in to comment.