A Model object is used for uni-directional or bi-directional data synchronization with widgets.
In this document:
Data model based on the constructor from the dojox/mvc/getStateful
module is widely used
due to the following features.
get
and set
methods to work with named properties.dojox/mvc/at
method.watch
method allows tracking an object property. It calls a custom callback method once the property
is changed. The application can deactivate the method at any time.
Generally, the method is used the same way as the Mozilla JavaScript’s watch
method.Get more details about the stateful models at the Dojo site, for example, read the dojo/Stateful document.
You may change data of the model using the standard set
method.
This method accepts two arguments: the name of the property being changed
and a new value. See details in Base Properties and Methods.
Using the business controls of the dojox/mvc
group, you can bind data
with widgets. Such binding creates a bidirectional or a unidirectional
mechanism for updating the bound widget and the data.
Furthermore, using dojox/mvc
you can synchronize changes in several
widgets. If they are bound with the same model, changes in one widget
will be applied to all widgets.
The simplest way of binding a model and a widget is to use the at
method of the dojox/mvc/at
module. This method accepts two arguments:
at(model, property)
.at(model.structure, property)
, or at(model.structure.sub-structure, property)
.In addition to direct model to widget binding, using the
at
method you can specify intermediate formatting of data. To do
this, you need first to set data binding with help of the
direction
method and then set data transformation methods in the
object passed to the transform
method.
The direction
method sets one of the following sync modes:
Bidirectional, for example:
cpu: at('model', 'cpu')
Unidirectional from model to widget, for example:
cpu: at('model', 'cpu').direction(at.from)
Unidirectional from widget to model, for example:
cpu: at('model', 'cpu').direction(at.to)
The transform
method accepts the following arguments:
Please note that it is not necessary to define the both methods. If the
data can change only in the model and cannot change in the widget,
it is sufficient to define only the format
method as in the following example.
require(["aps/load", "dojox/mvc/getStateful", "dojox/mvc/at", "aps/ready!"],
function(load, getStateful, at) {
var model = getStateful({
"platform":
{
"arch": "i386",
"os":
{
"name": "Linux",
"version": "centos-6"
}
},
"cpu": 76
});
load([[ "aps/Output", {
content: "CPU: ${cpu}",
cpu: at(model, 'cpu').
direction(at.from).
transform( {
format : function (value) {
return value + "%";
}
})
}]], "output");
}
);
The following examples illustrate various ways of model to widget binding.
The binding is established during activation of a widget by means of the load
method.
require(["dojox/mvc/getStateful", "dojox/mvc/at", "aps/load", "aps/ready!"],
function(getStateful, at, load){
var model = getStateful({
"platform": {
"arch": "i386",
"os": {
"name": "Linux",
"version": "centos-6"
}
},
"num": 0
});
load([[ "aps/Output", {
content: "This is ${name} - ${version}",
name: at(model, 'num'),
version: at(model.platform.os, 'version') }
]], "output");
setInterval(function(){ model.set("num", model.num+1); }, 1000);
});
A widget can be created and then activated dynamically in a program code.
require(["aps/Output", "dojox/mvc/getStateful", "dojox/mvc/at", "aps/ready!"],
function(Output, getStateful, at){
var model = getStateful({
"platform":
{
"arch": "i386",
"os":
{
"name": "Linux",
"version": "centos-6"
}
},
"num": 0
});
var out = new Output({
content: "This is ${name} - ${version}",
name: at(model, 'num'),
version: at(model.platform.os, 'version')
}, "output");
out.startup();
setInterval(function(){ model.set("num", model.num+1); }, 1000);
});
Bidirectional synchronization between a model and a widget may lead to infinite recursion. This can happen when a widget automatically changes the value synced with a model property.
Currently, the widgets escape special HTML characters if they exist in a string assigned to some
of their properties.
It means they substitute such a character with the “&entity_name;” or “&entity_number;” sequence
in accordance with the HTML codes table .
Suppose, there is a bidirectional synchronization between the value
of an aps/Output
widget and a model string property. This case is prone to the following scenario:
The synchronization process cycles until the respective stack overflows.
For this reason, to have more robust code, use the unidirectional synchronization wherever possible, for example:
["aps/Output", {
label: "OS",
value: at(model, 'text').direction(at.from)
}]