Binding data and configuration options
context.binding
The binding object, if defined, provides access to data that is bound to a view. There is at most one data binding declared for each view.
You can
access data that is bound to a view by using the construct:
this.context.binding.get("value")
, where value is a special
property name that returns the data binding. For example, if a view is bound to local.phoneBook.title
, then the view can get the phone book's
title as follows:
if (!! this.context.binding){
var title = this.context.binding.get("value")
}
The main reason for views to bind to data is so that the view can be notified if the
bound data has been modified. The view framework detects data changes in the bound object, and
automatically notifies the view by calling its change
event handler function. It is
important to note that these notifications will be sent to the view only if the binding object
itself changes, but not if any of its properties or sub-properties change. The following sections
discuss the different data types and outline the cases where additional code is required for the
view to receive notification of a data change.Binding to simple and complex data types
For simple data types such as strings and numbers, the view framework detects data changes and
automatically notifies the view of the change. For example, when a view is bound to the simple
string type local.phoneBook.title
, the view's change()
function is
called with a change event that specifies that the title changed and its new value. All the views
that are bound to local.phoneBook.title
are notified.
local.phoneBook
, not a simple type like a
String. The object phoneBook
has several properties, one of which is
title
. If there is a change to the title
property, the change
function is not called, because the view is bound to the phoneBook
object, not the
title
property. The change function is only called if the entire
phoneBook
object is changed. If you need a view to know if a property of a complex
object has changed, you must manually bind the view to the property by using the
bind()
or bindAll()
function. Note that you can use the
bind()
and bindAll()
functions in the same way for configuration
options.bindAll()
function only handles one level deep
in the object tree, so if the object has multiple levels (nested objects), the view needs to call
bindAll()
multiples time for each object level.- bind(path, callback, [scope])
- Notifies the view via callback if a specified property has changed. Scope is an optional parameter that specifies the context scope of the callback. Returns a handle to the callback.
- bindAll(callback, [scope])
- Notifies the view via callback if any property on the object has changed. Scope is an optional parameter that specifies the context scope of the callback. Returns a handle to the callback.
For the callback signature, see the function(event) topic.
var binding = this.context.binding.get("value"); //this is a complex object
this.property2Handle = binding.bind("property1.property2", function(e) {some code}, this);
this.property3Handle = binding.get("property3").bindAll(this.myBindAllChangeHandler, this);
......
this.mybindAllChangeHandler(event) { .....};
In the example, the view is bound to a
complex object and sets a change handler to be notified if
binding.property1.property2
(which is a string) changes. It also sets another
change handler to be notified if any sub-property of property3
changes. In both
cases the scope in which the change handler is called is the view's this
scope.
Binding to a list type
When you bind to a list, the view is automatically notified when the entire List object changes.
For example, consider that the view is bound to the list local.phoneBook.person[]
.
If a new person list is created and set to the view's binding, for example using the server script
syntax tw.local.phoneBook.person = new tw.object.listOf.person();
the framework
automatically notifies the view of the change.
Binding to list updates
bindAll()
function. In the following code example, the view's
listUpdated
function is called whenever a list element is added, removed, or
replaced.var binding = this.context.binding.get("value"); //this is a List object
this.bindAllHandle = binding.bindAll(this.listUpdated, this);
Binding to list properties
In addition to the elements of a list, a list also has special properties, such as a property that defines the list elements that are selected by a user. The special properties are described in the following table.Property | Type | Description |
---|---|---|
listAllSelectedIndices | Array | The indexes of the list elements that are selected by a user. There can be more than one selected index. When you set listAllSelectedIndices, you pass in the indexes in an array. Use listAllSelectedIndices when updating the list selection. |
listAllSelected | Array | An array of all the elements that a user has selected. Use listAllSelected to subscribe to a change to this property. This property is read-only. |
listSelectedIndex | Integer | The index of the selected element. This value corresponds to the value of the index 0 element of the listAllSelectedIndices array. Use listSelectedIndex to subscribe to a change to this property. This property is read-only. |
listSelected | Object | The selected element. This value corresponds to the value of the index 0 element of the listAllSelected array. Use listSelected to subscribe to a change to this property. This property is read-only. |
bindAll()
function does not include these special properties.
bind()
function. In general, it is sufficient to subscribe to
one special property (that is, it is not necessary to subscribe to all of the special properties).
The following example code could be added to a load event handler to call a view's
indicesChanged
function whenever the value of
listAllSelectedIndices
changes.var binding = this.context.binding.get("value"); //this is a list
this.selectedIndicesHandle = binding.bind("listAllSelectedIndices", this.indicesChanged, this);
Accessing list elements
- Use
get("value")
to get the list object. For example:list = this.context.binding.get("value")
- Use
get(index)
to obtain the indexed element. For example:list.get(0)
to obtain the first element. - Use
get(property)
to obtain the value of the property. For example:list.get("listSelected")
to obtain the value of thelistSelected
property. Use similar syntax to obtain the values of all other properties. - Use
items
to get an array that represents the underlying elements of the list. For example,list.items
. The data returned byitems
should not be modified.
List operations
The following APIs are used to modify a list and to get information about a list.- To add an object, use
list.add(item)
. For example,this.context.binding.get("value").add(item)
- To remove an object, use
list.remove(index)
, For example,this.context.binding.get("value").remove(0)
- To replace an object, use
list.put(index, item)
. For example,this.context.binding.get("value").put(0, item)
- To get the length of a list, use
list.length()
. - To get an indexed element or property of the list, use
list.get(index | property)
. See Accessing list elements earlier. - To programmatically update the selected property in the list, use
list.set(property)
. For example,this.context.binding.get("value").set("listAllSelectedIndices", [1, 2, 3]);
Cleaning up bound resources
bind
or bindAll
function returns a handle which can be used to
clean up the binding. You should release the bound resources either in the unload()
event handler, or each time the whole binding object is changed. When a binding data change occurs,
a view needs to unbind the manual binding, and rebind to the context.binding
object
by calling bind
and bindAll
again. For example, add the following
code in the change event handler:if (event.type != "config"){
var binding = this.context.binding.get("value"); //this is a list
// assumes that this.selectedIndicesHandle was initialized in the load function
this.selectedIndicesHandle.unbind();
this.selectedIndicesHandle = binding.bind("listAllSelectedIndices", this.indicesChanged, this);
// assumes that this.selectedIndicesHandle was initialized in the load function
this.bindAllHandle.unbind();
this.bindAllHandle = binding.bindAll(this.listUpdated, this);
}
Configuration options
In addition to data, views also can be bound to configuration options. A view can have multiple configuration options. For example, the label of a button control is a configuration property. The values for the configuration can be retrieved using the view'sthis.context.options
object. The object context.options
contains a predefined metadata property in addition to user-defined properties that are configurable
for a view.
Option | Type | Description |
---|---|---|
label | String | The label value of the view, if one exists |
visibility | String | The visibility settings for the view. Valid values are:
"DEFAULT" | "EDITABLE" | "REQUIRED" |
"READONLY" | "NONE" | "HIDDEN" . See The context object.
DEFAULT is the code equivalent to Same as parent that users
see on screen in a Visibility list.Important: Tables have a Disable
click-to-edit configuration property. The default value is false, which means that views
contained within that table use the visibility settings of the table. That is, the views in a given
cell are
READONLY until the user clicks in the cell. The views are then
EDITABLE until the user clicks anywhere outside of the cell. The views revert to
being READONLY . When Disable click-to-edit is true, these
views use their own visibility settings.Important: Setting
the visibility to
REQUIRED does not validate whether a user has entered or set a
value. You must provide code that does this checking by, for example, implementing a validation
service for the coach that contains the view. |
labelVisibility | String | The visibility settings for the label. Valid values are
"SHOW" | "HIDE" . |
helpText | String | The view can use this property as hover text |
className | String | The CSS class name(s) specified. Normally a view does not need to use this as the CSS class names are inserted into the view's DOM attribute. |
htmlOverrides | Map | A name-value pair map that represents the HTML attribute specified. These name-value pairs are inserted into the view's DOM attribute. |
- To get a view's predefined options, use
this.context.options._metadata.*
. For example, to get a view's visibility option, usethis.context.options._metadata.visibility.get("value");
- To set a view's predefined options, use
this.context.options._metadata.*
. For example, to set a view's visibility option, usethis.context.options._metadata.visibility.set("value", newValue);
- To get a user defined configuration option, use
this.context.options.myOption.get("value");
, wheremyOption
is the option name. - To set a user defined configuration option, use
this.context.options.myOption.set("value", newValue);
, wheremyOption
is the option name.
To serialize the data binding object to a
JSON string, you can call the toJson()
function on the data binding object. To get
a basic JavaScript object that represents the data binding, you can call
toJSObject()
.