Intermediate

Data Binding and Syncing

When you have several views (components) on the page that share the same data source, you can connect them, so that any changes in one of the views would trigger changes in the others. There are three ways to connect components:

  • binding
  • syncing
  • importing

All ways suppose that there is the master component and the slave component(s). The master view serves as the data source for the slave one(s).

Binding and Syncing - Difference

When you bind components, it means that when you select an item from one component, this item will be the data source for another component. Most typically, binding is used with some data component (master) and a form / htmlform (slave).

When you sync components, it means that all changes in the datastore of one component (such as adding, deleting, updating, filtering, sorting, etc.) are reflected in the other component at once.

Data Binding

How to Use

You can bind components by calling the bind() method from the slave component and passing the master component as a parameter.

$$("form1").bind($$("list1"));

If you select an item in the list, the form will be filled with the data from that item.

Note that the name properties of the input fields of the form must be the same as data field names in the component data.

// in data
{ name:"Jane", age:23 }
// in form
{
    view:"form", elements:[
        { name:"name", view:"text" },
        { name:"age", view:"text", type:"number" }
    ]
}

Changes in the slave component will affect the master. If you edit the data in the form and then save it, the list item will be updated. To save the changes, call the save() method of the form. Note that only the forms that have the master have the save() method.

$$("form1").save();

A slave can also be disconnected from the master by the unbind() method:

$$("form1").unbind();

Related sample:  Creating Basic App: Step 3

Related sample:  Binding to a Native HTML Form

How it Works

Binding is no magic. It is syntactic sugar for a more straightforward approach to connect components with events. For example, the same can be done for a form and a list with:

// select an item in the list and fill the form
$$("list1").attachEvent("onAfterSelect", function(id){
    var item = this.getItem(id);
    $$("form1").setValues(item);
});
 
// save form data into the list
view:"form", id:"form1", elements:[
    // ...
    {
        view:"button", value:"Save", click:function(){
            var item = this.getFormView().getValues();
            $$("list").updateItem(item.id, item);
        }
    }
]

For instance, this approach is the one you should choose if you use Webix Jet, because there a form and its master component are most likely in different files and binding is impossible.

Advanced Binding

Data binding has more advanced options to explore:

  • additional parameters for customization;
  • binding hierarchical structures;
  • event system;
  • a native API to set the default data for cases when no record is selected in the master control;
  • cursor concept to bind to a DataCollection.

Study the corresponding article for details.

Syncing Components

Data syncing allows a copy of the data from one data-presenting component and pass it to the other one. Any change in the master component results in the same change in the slave one. As for changes in the slave, only updates are reflected on the master. Read more about data operations.

There can be more than one slave component. In this case, all slaves change simultaneously on master component change.

This is how you can sync two components:

$$("slave_component").sync("master_component");

Syncing with a Callback

You can define a specific behavior for a slave widget. For example, you can filter out records, group data, etc. before they will be shown in the slave. For this, define a callback function as the second parameter of the sync() method.

Filtering

For instance, this is how you can filter the data in the callback. Here only the films shot after 1994 will be shown:

$$("dview2").sync($$("listA"), function(){
    this.filter(function(data){
        return data.year > 1994;
    });
});

Read more on data filtering.

Grouping

You can also group data before it is displayed in a slave component, for example:

$$("chart").sync($$("customers_grid"), function(){
    this.group({
        by:"status",
        map:{
            value:["value","count"]
        }
    });
});

Read more on data grouping.

Unsyncing

You can disconnect components by calling the unsync method for the slave component:

$$("dview2").unsync();

Data Operations

When views are synced, any data operation on the master is reflected on the slave. The master defines the data in all its slaves. Slaves can only update data items on the master. Therefore you should:

  • update data on the slave or on the master
$$("slave").updateItem("itemId", { new_data:"some data" });
// or
$$("master").updateItem("itemId", { new_data:"some data" });
  • add or delete items on the master only
$$("master").add({ new_data:"some data" });
$$("master").remove("itemId");

Notes for Webix Jet Users

If you develop apps with Webix Jet, syncing of visual components is impossible, because the views are most often in different modules and the UI is separated from the data loading/saving logic. The most common approach for Jet is to create a data model with a DataCollection and import it into the views.

Data Import

Data import allows synchronizing the data of two components (one of them can be a DataCollection) without tracking data changes afterwards.

The slave component will be populated with the data of the master with the importData method:

$$("listB").data.importData($$("listA"));

Note that it's a DataStore method, so it should be called for the data of the component.

Also note that the importData method is tricky. It does not copy the data, so item updates in both widgets will be shared after refreshing.

To fully copy the data from one widget into another one, you need to apply:

$$("listB").parse($$("listA").serialize());
Back to top