Data binding makes the selected record of one component the data source for another one. A typical use case is binding a form with a data component, e.g.:
$$("myform").bind($$("list"));
// ...
$$("myform").save();
Here you will find more details and use cases of data binding.
The data cursor is used to control the position on the active data item. The cursor stores the ID of a data item that is currently selected in the master component.
When an item is selected in a data component, the component places the cursor on the selected item. Since there is no selection in DataCollection, it cannot focus on the item. You have to do it. That is where the DataCollection cursor is used.
Cursor should be set if several components are bound to or synced with one and the same source, e.g. a DataCollection. It is needed to avoid conflicts between different components referring to one and the same data source and making changes in it.
You can get and set cursor position with the help of the following methods:
var cursor = master.getCursor();
The cursor can be deleted to remove the current bind link:
master.setCursor(null);
If a form (slave) is bound to a list (master) and the cursor is removed from the list, the form will be emptied.
Cursor is as well useful when working with DataCollections.
When you bind components, the slave component gets three events:
$$("files").bind($$("folders"));
$$("files").attachEvent("onBindApply", function(){
// makes the preview template empty
$$("preview").setHTML("");
});
This concerns only data components that have the template property in their configuration. In a form and an htmlform binding is set according to the names of their inputs.
When no selection is made in the master component, the slave component would show undefined values. You can set the default values that should be displayed when nothing is selected. Use the defaultData property of the master:
webix.ui({
rows:[
{
view:"list",
template:"#rank#.#title#",
// data: ...
defaultData:{
rank:"0",
title:"default Item"
}
},
{ view:"template", template:"#rank#.#title#" }
]
})
$$("template1").bind($$("list1"));
Look to CollectionBind API for more details.
When a form is bound to a component, the data from the selected item is pushed to the form. Any changes you make within the form are saved automatically to the selected item. It happens on calling the save(); method:
$$("myform").save();
If the form was not filled with the data from the master when the save() method was called, the form will add a new element into the master.
You can save some extra data together with the values from the form. Get the form values, add necessary properties there and pass the resulting object to the form.save() method:
var values = form.getValues();
values.myfield = "My value";
form.save(values);
If you have two forms bound to one and the same component and you save each of the forms separately, the data from the previously saved one is lost.
There are two possible solutions:
1) To get values from both forms and uniting them with extend:
var v1 = $$("form1").getValues();
var v2 = $$("form2").getDirtyValues();
$$("form1").save( webix.extend(v1, v2, true) ); // combine values from both forms
2) To use the saveBatch method that makes simultaneous saving of several forms together with the getDirtyValues method that prevents data overwriting.
$$("datatable1").saveBatch(function(){
$$("form1").save();
$$("form2").save( $$("form2").getDirtyValues() );
});
The getDirtyValues method returns only the fields that were changed in the form.
Customization is possible only if the slave component has DataStore or TreeStore (DataTable, Tree, List, Chart, etc).
You can change the default pattern, according to which the records in a slave component are filtered with the help of rules. You can specify a rule as a function or a string and pass it as the second parameter of the bind() method.
As a function, a binding rule receives 2 parameters:
For example, let's bind a list to a richselect and set the rule, according to which the list data are filtered depending on the selected option in the richselect:
Slave list displays records with the category equal to the master value
$$("list").bind($$("richselect"), function(slave, master){
return slave.category == master;
});
Related sample: List Data Bound to Richselect
You can also use the rule function to cancel binding at runtime. For example, let's bind two Datatables and cancel binding if no record is selected in master:
Slave datatable displays only records with movie property equal to master record ID
gridb.bind(grida, function(slave, master){
if (!master) return false; //canceling binding
return master.id == slave.movie;
});
Related sample: Linking Tables
Pay attention that the selected value for the master view should be set after the data are loaded.
A rule string is helpful when you bind a view to a hierarchical data component (e.g. Tree, TreeTable). The rule can help you decide which data levels to push to the slave. The rule can contain the following flags:
Let's bind a DataTable to a Tree and push the children of the selected item into the DataTable:
$$("grid").bind( $$("tree"), "$level");
// where the tree data of the selected node is something like
{ id:"3", value:"Node 3", data:[
// will be shown in slave component
{ id:"3.1", value:"Subnode 3.1" },
{ id:"3.2", value:"Subnode 3.1" }
]}
Related sample: Tree Data Binding
This feature is also handy for binding with a hierarchical component. By default, the children of a data item are introduced by the data key in all the supported data formats. If you want to push data stored by a different key ("records", for example), you can pass its name as the format string. The format is passed as the third parameter of the bind() method.
Let's bind a DataTable to a Tree and use the $data rule together with the records format:
$$("grid1").bind( $$("tree"), "$data", "records");
// where the tree data of the selected node is something like
{ id:"3", value:"Node 3", records:[
// will be shown in slave component
{ id:"3.1", value:"Subnode 3.1" },
{ id:"3.2", value:"Subnode 3.1" }
]}
Related sample: Tree Data Binding: Subdata
Format can be set as a function where you can define the binding behavior manually. For example, let's define a function that will push both data and records from the selected node:
$$("grid2").bind( $$("tree"), "$data", function(obj, source){
if (!obj) return this.clearAll();
var fulldata = [].concat(source.data.getBranch(obj.id)).concat(obj.records);
this.data.importData(fulldata, true);
});
Here we get item children with the help of a getBranch() method, combine them with data set by records key and import the resulting array into slave datatable.
Related sample: Tree Data Binding: Subdata
As a rule, a slave component does not communicate directly with the server side. It receives data from its master, and the changed data are sent first to the master that handles communication with the server.
However, you can get server-side data for the slave based on master selection with the help of the dataFeed functionality.
webix.ui({
view:"form",
id:"myform",
// ...config
dataFeed: "slave_data.php"
});
$$("form1").bind("datatable1")
Related sample: Datatable: Binding with Form
dataFeed defines the URL that will be used by the slave and sends a request when selection in the master component changes.
The functionality works the same for a form and collections (data components) yet the URL parameters sent with a request differ:
where obj is the selected data item in the master component.
Back to top