Intermediate

DataProcessor

Webix DataProcessor is a functional library that lets you to ‘communicate’ with server-side backend. It

  • resides on the client side as a mixin of Webix library;
  • listens to component events - data adding, updating, moving (should be enabled separately) and removing - and passes changed data as well as operation performed (insert, update, delete) to the server script in POST request.
  • handles data validation before passing to server script;
  • can be used for any UI component and DataCollection.

Without DataProcessor, you need to attach corresponding functions to component events (onAfterInsert/Update/Delete) to get data ready for processing.

You can find the full list of DataProcessor methods, properties and events in the API Reference.

DataProcessor Initialization

DataProcessor object can be initialized in both long and short forms. Compulsory parameters include:

  • url, a path to your own server script or connector-based one (described in Server Side Connector). In any case, it should be the script that enables data loading from the database into the component;
  • master, a component or DataCollection you will use the dataProcessor with.

Other parameters (mode, validation rules, on, etc.) and optional and can be found here.

Implicit Initialization via Save Property

When you define url (path to the necessary script) as value of save property for the needed component (master) - DataProcessor is automatically initialized:

webix.ui({
    view:"datatable",
    //..config..
    url: "data.php", //script that links to DataConnector and loads data
    save: "connector -> data.php" //the same script used for data processing
 
    //or
    url:"data_load.php", //your custom script for loading
    save:"data_save.php" //you custom script for saving
});

Short Form

A short form connects the previously created dataProcessor to the component, but if there isn't any, it creates the new dataProcessor.

Short Form (master, url)

webix.dp("mylist", "some_script.php");

Long Form

With a long form you make use of the new constructor where you create an object through object literals.

Full Form

dp = new webix.DataProcessor({
    url: "data.php", 
    master: $$('mylist'),
    //optional properties
});

Related sample:  Server-side Integration: List

A long initialization form allows for setting an ID for the dataprocessor. Otherwise, it is given an auto-generated one.

Getting DataProcessor Object

Dataprocessor features a set of methods and properties that can be used to change default processing pattern. To make use of them, you need to get to a dataprocessor object, which can be achieved with the help of Webix dp method:

  • getting a dataprocessor initialized for a component with the specified ID:
var dp = webix.dp("mylist"); //returns dataprocessor object for "list" view
  • getting a dataprocessor with the specified ID
var dp = webix.dp.$$("mydp");

Data Processing Operations

DataProcessor interprets client-side operations performed on each data item and defines the type of data action for it:

The default processing looks as follows:

  • If remove() function is called within the component, action type is delete;
  • If editing is done, or update() function is called, data action is of an update type;
  • If you add() data to the component, the data action is insert.

This data action together with data of edited/added/deleted record is sent to server script the moment any editing operation is performed. Data action is passed as:

  • !nativeeditor_status parameter in case of implicit DataProcessor initializing (with save property) and simultaneous usage of connector;
view:"list",
save:"connector->myscript.php" //link to Server Side Connector
  • webix_operation parameter in all other cases.

It looks like this:

id  7
title   The Shawshank Redemption
webix_operation delete

And other protocol with implicit Dataprocessor initializing for connector-based scripts:

1_!nativeeditor_status  update
1_birthday  1965-08-19
1_id    1

The moment Dataprocessor returns data, script execution begins (if other is not stated):

  • If server side integration is enabled with a Server Side Connector, the connector automatically generates database request corresponding to action type to treat changed data;
  • For custom scripts, you get webix_operation and other data via POST request and write corresponding queries for each type of operation.

DataProcessor for Drag-n-Drop and Data Moving

DnD operations and data item moving can be tracked by DataProcessor like any other CRUD operation provided that you switch on DataProcessor trackMove functionality.

new webix.DataProcessor({
    master: tree,
    url: "...",
    trackMove:true
});

Related sample:  Server-side Integration: Tree

DataProcessor EventSystem and Error Tracking

DataProcessor events (listed in API reference) can be used for different purposes. For instance, the events can help you:

1) Modify data before it's gone to server with the onBeforeDataSend event that takes the whole data object as parameter:

dp.attachEvent('onBeforeDataSend', function(obj){
    obj.data.StartDate = webix.i18n.dateFormatStr(obj.data.StartDate);
});

2) Track successful and unsuccessful server-side responses separately with the help of onAfterSync and onAfterSaveError events respectively:

Successful server response

dp.attachEvent('onAfterSync', function(statusObj, text, data, loader){
    var response = data.xml(),
    hash = response.data;
    //hash {status:"", id:"", newid:""}      
});
  • status - the status of operation ("success"/"error"/"invalid");
  • id - obligatory, item ID that was sent to the server for update;
  • newid - item ID returned from the server after update.

Unsuccessful server response

dp.attachEvent('onAfterSaveError', function(id, status, response, details){
     var operation = this.getItemState(id).operation; //operation that was performed
});

In case of an error during saving, response status will always be 'error' while type of operation is derived by getItemState method.

Getting to a master component from DataProcessor

Inside DataProcessor event handlers you can reach the master component through DataProcessor configuration object:

dp.attachEvent('onSomeEvent', function(id, status, obj){
   var grid = this.config.master; //this == DataProcessor
});

Data Updating from Server Response

As it was stated earlier, the new ID from response of insert request will automatically replace the temporary client-side ID. This is part of default DataProcessor behavior, and no specific actions are required.

Additionally, you can enable automatic data update for all fields taking part in insert and update operations. It requires the following additions to the code:

  • tune server-side response to return the whole data object (not only status or IDs);
  • enable DataProcessor autoupdate functionality:

Either during explicit DataProcessor definition

new webix.DataProcessor({
    updateFromResponse:true, 
    master:"datatable1",
    url:"..."
});

Or when defining DataProcessor implicitly

view:"datatable",
save:{
    url:"...", 
    updateFromResponse:true
}

Related sample:  Datatable: Updating

It can be useful for REST-full applications or when you need to fill in client-side fields which values can be calculated only on server side, etc.

Changing Default Processing Logic

The event system for dataProcessor helps change the default processing logic right on client-side.

To alter processing, you should manually attach processing function to the necessary DataProcessor event (onBeforeDelete, onBeforeInsert, onBeforeUpdate). For instance, set update action type on onBeforeDelete thus making connector issue UPDATE request instead of DELETE.

This is how we change deletion from database by updating this record:

webix.ui({
    view:"datatable", 
    id:"grid",
    ..// config options
    url:"data/employee.php", 
    save:"connector->data/employee.php"
 });
 
..//function redefining removal into updating
 
webix.dp($$("grid")).attachEvent("onBeforeDelete", function(id, action){
        action.operation = "update";
        action.data.deleted = webix.i18n.parseFormatStr(new Date());
});

where..

  • id - the ID of the item being processed;
  • action - DataAction object;
  • operation - the database operation being performed (action type);
  • data - refers to component inner DataStore. Here we can get to the desired data item property (action.data.property_name).

Now, when a record is removed from the component, a field deleted of this record is updated in the database table. The current date is set into it to track the moment when the record was removed on the client side.

Learn more about the possibilities of data manipulation on the client side in related articles:

Canceling and Enabling Dataprocessor for Some Operation

Canceling DataProcessor

Not any client-side update is to be saved to server. To temporarily cancel DataProcessor you can:

  • either apply ignore function to the Dataprocessor object.
webix.dp("grid").ignore(function(){
    $$("grid").add(data);   
});
  • switch Dataprocessor off during the update operation:
dp.on();
$$("grid").add(data);   
dp.off();
  • cancel automatic data sending via DataProcessor autoupdate property.
//initially during dp configuration
new webix.DataProcessor({
    updateFromResponse:true, 
    master:"datatable1",
    url:"...",
    autoupdate:false
});  
 
//dynamically
webix.dp($$("datatable1")).define("autoupdate", false);

Enabling Dataprocessor

The following concerns only disabled DataProcessor or the one with the changed behavior or if you need to emulate DataProcessor logic. In other cases DataProcessor performs the below described actions automatically.

To enable DataProcessor, and hence, trigger, sending its data to server, save method should be used with item ID and operation name as parameters:

webix.dp($$("datatable1")).save(1, 'update');

To get all changes in the component and send them to server, send method should be used:

webix.dp($$("datatable1")).send();

Data Validation with DataProcessor

Data validation is enabled by including specific rules for input field. You can read about them here. With rules specified, the validation process starts each time you try to save data to the database.

dp = new webix.DataProcessor({
    rules:{
        $all:webix.rules.isNotEmpty 
    },
    url: "save.php", 
    master: $$('mylist')
});

Sending Headers with DataProcessor-based Requests

There exists no possibility to send headers with DataProcessor requests as they are executed in background. However, you can catch Webix onBeforeAjax request to modify ANY Ajax request issued from the page:

webix.attachEvent("onBeforeAjax", 
    function(mode, url, data, request, headers, files, promise){
        headers["Content-type"]= "application/json";
    }
);

Note that Webix Ajax module features a built-in functionality for sending headers with server side requests. The above solution is only for DataProcessor Ajax requests.

Related Article

Back to top