Webix provides a special mixin called DataDriver. It allows you to manage loading of data into Webix components in the formats different from JSON a lot easier. The mixin provides a set of predefined data parsers for the common formats: json, xml, html, csv, jsarray, excel and htmltable. Data drivers convert data from any of these formats to JSON to make them suitable for data components to work with.
In case of XML you can redefine the following:
Element | Type | Code |
---|---|---|
data tag | xpath |
|
configuration tag | xpath |
|
child tag | tag name |
|
For example to alert the default processing of XML data you can add the following line to your code:
webix.DataDriver.xml.records = "/*/book";
webix.DataDriver.xml.child = "part";
The line above will redefine data parsing logic for all XML sources. If you want to separate default and custom logic you need to create a custom XML processor on the base of the default one.
var myxml = webix.DataDriver.myxml = webix.copy(webix.DataDriver.xml);
myxml.records = "/*/book";
myxml.child = "part";
Related sample: Tree: XML Dataset
Child tags can be specified by a function:
var myxml2 = webix.DataDriver.myxml2 = webix.copy(webix.DataDriver.xml);
myxml2.records = "/*/book";
myxml2.child = function(obj){
if (obj.$level == 1)
return obj.part;
if (obj.$level == 2)
return obj.page;
}
Related sample: Tree: XML Dataset
It is possible to define row and cell separators:
webix.DataDriver.csv.row = "\n";
webix.DataDriver.csv.cell = ",";
The above line resets processing of all the CSV sources in the application. To avoid this, create a custom CSV format:
var mycsv = webix.DataDriver.mycsv = webix.copy(webix.DataDriver.csv);
csv.row = "\n";
csv.cell = ",";
You can redefine which tag in HTML will be processed as a data tag:
webix.DataDriver.html.tag = "LI";
The above line resets processing of all the HTML sources in the application. To avoid this, create a custom HTML format:
var myhtml = webix.DataDriver.myhtml = webix.copy(webix.DataDriver.html);
html.tag = "LI";
You can redefine what object property stores sub-items (used for hierarchical dataset, e.g. tree, treegrid, grouplist, etc.):
webix.DataDriver.json.child = "data";
The above line resets processing of all the JSON sources in the application. To avoid this, create a custom JSON format:
var myjson = webix.DataDriver.json = webix.copy(webix.DataDriver.json);
myjson.child = "data";
Child tag can also be specified as a function, if you want to create different tags for child items of different levels:
myjson.child = function(obj){
if (obj.$level == 1)
return obj.parts;
if (obj.$level == 2)
return obj.pages;
};
Any custom child collection will be converted to "data", while the original child fields are removed from the data item during parsing.
Unlike static tags, dynamic fields are not removed from data items, because the field name varies. If you need to remove them, do it explicitly in the child method:
myjson.child = function(obj) {
var data;
if (obj.$level == 1) {
data = obj.parts;
delete obj.parts;
}
if (obj.$level == 2) {
data = obj.pages;
delete obj.pages;
}
return data;
}
All data drivers share the following methods:
//converts string to object
var data = driver.toObject(data);
//returns array of all records in data source
var records = driver.getRecords(data);
//returns single data object
var data = driver.getDetails(records[0]);
//runs xpath
var elements = driver.xpath("/some/xpath", data);
//converts xml tag to json object
var obj = driver.tagToObject(elements[0]);
//converts string to js data-types, numbers and booleans
obj = driver.assignTypes(obj);
In addition to the built-in data types, it is possible to define custom ones by creating a custom data driver.
The structure of a driver is the following:
webix.DataDriver.driverName={ //driverName - the name of the type
toObject:function(text,xml){
// ...
return text;
},
getRecords:function(data){
var result = [];
// ...
return result;
},
getDetails:function(data){
var result = {}
// ...
return result;
},
getInfo:function(data){
return {
size:0,
from:0
};
}
};
You can check the structure of the existing data drivers in the Webix source code (/sources/load/drivers/driver_name.js).
For a start, we have some data that we want to use as a new data type. The first thing we need to make with this data is to convert it into an intermediate object (an object that will be used as an input parameter in other functions).
1 . So, our first step is the toObject(text, xml) function. The function is called after data loading or directly in the parse method and returns the intermediate data object:
2 . Then, we form an array of records using data from our intermediate object with the help of the getRecords(data) function. It takes the only parameter:
3 . Having an array of records we need to specify a set of properties for each single record via the getDetails(data) method. It takes the only parameter:
4 . The last action makes sense just for dynamic data loading scenarios. It's about the getInfo(data) function that gets total count of the data and position at which new data needs to be inserted. The method accepts the following parameter:
The function returns an object with the following properties:
JSON and XML data drivers add extra properties to this object:
So, taking these four or even three steps you can specify any data type and then use it while developing.
Creating a completely new driver is not a most common task, but user may need to alter the processing logic of some built-in driver.
It can be done with the help of Webix extending pattern that allows to extend any JSON object:
webix.DataDriver.custom = webix.extend({
records:"/data/items/item",
getDetails:function(obj){
var res = {};
var cells = this.xpath(obj, "cell");
for (var i = 0; i < cells.length; i++)
res[cells[i].getAttribute("id")] = this.nodeValue(cells[i]);
return res;
}
}, webix.DataDriver.xml);
Related sample: Loading from Custom XML
Back to top