Building Apps with Webix Jet
Data and Server Side
Loading Data
export default class DataView extends JetView {
config(){
return { view:"datatable", autoConfig:true, data:[
{ id:1, title:"The Godfather", ... }
]};
}
});BAD
import {data} from "models/records";
export default class DataView extends JetView {
config(){
return { view:"datatable", autoConfig:true };
}
init(view){
view.parse(data);
}
});GOOD
Shared Data
//models/records
export const data = new webix.DataCollection({
data:[
{ id:1, title:"The Godfather", ... }
]
});
//or
export function getData(){ return data; };
import {data} from "models/records";
export default class DataView extends JetView {
config(){
return { view:"datatable", autoConfig:true };
}
init(){
view.parse(data);
//or view.sync(data);
}
});Shared Data - Backend
//models/records
export const data = new webix.DataCollection({
url:"/some/records",
save:"rest->/some/records"
});
import {data} from "models/records";
export default class DataView extends JetView {
config(){
return { view:"datatable", autoConfig:true };
}
init(){
view.sync(data);
}
});Dynamic Data
//models/records
export function getData(){
return webix.ajax("/some/records");
}; import {getData} from "models/records";
export default class DataView extends JetView {
config(){
return { view:"datatable", autoConfig:true }
}
init(){
view.parse(getData());
}
});Dynamic Data - Saving
//models/records
export function getData(){
return webix.ajax("/some/records");
};
export function saveData(id, operation, data){
if(operation =="update") //"add", "delete"
return webix.ajax().put("/some/records", data);
...
};
import {getData, saveData} from "models/records";
export default class DataView extends JetView {
config(){
return { view:"datatable", autoConfig:true, save:saveData };
}
init(){
view.parse(getData());
}
}Remote models
export default class DataView extends JetView {
config(){
return {
view:"datatable",
autoConfig:true,
url:"/some/records",
save:"rest->/some/records"
};
}
});Dynamic loading
- { data:[], total_count:10000, pos:500 }
- scroll or node open -> GET next portion
Server filtering and sorting
- filter or sort -> GET new data from server
Relatively small
Used many times
Shared Data
Relatively big
Used once
Dynamic Data
AND
OR
Huge data
Prototyping
Remote Models
OR
Be pragmatic!
Async data: Promises
Webix Promise Interface
var promise = webix.promise.defer();
promise.then(() => {
console.log(message);
}).fail(() => {
console.log(err);
});
promise.resolve("Success!"); let promise = new Promise((resolve, reject) => {
//smth async
setTimeout(() => {
resolve("Success!");
}, 250);
});
promise.then((message) => {
console.log(message);
}).catch((err) => {
console.log(err);
});JS Promises
Async data: Promises
Webix Ajax Interface
//load by method
let promise = datatable.load(url);
promise.then(() => {}).fail(() => {});
//load by property
{ view:"datatable", id:"dt", url:url }
$$("dt").waitData.then(() => {}).fail(() => {}); let promise1 = webix.ajax(url, params); //load
let promise2 = webix.ajax().post(url, params); //save
promise1.then((data) => {}).fail((err) => {});
promise2.then((data) => {}).fail((err) => {});Ajax -related promises in widgets
Wait for loading:
- view.waitData.then(..),
- view.load(url).then(..),
- loading events, e.g onAfterLoad
Async data: Use at once
import {data} from "models/records";
import {options} from "models/options";
export default class DataView extends JetView {
config(){
return {
cols:[
{ view:"datatable", id:"table", columns:[
{ id:"title", fillspace:true},
{ id:"categoryId", collection:options}
]}
]
};
}
init(view){
this.$$("table").sync(data);
}
}
[
{ id:1, title:"...", categoryId:1 },
{ id:2, title:"...", categoryId:2 },
{ id:3, title:"...", categoryId:3 }
][
{ id:1, value:"Crime"},
{ id:2, value:"Thriller"},
{ id:3, value:"Drama" }
]Data
Options
Async data: Wait until loaded
view/collection.waitData
import {data} from "models/records";
export default class DataView extends JetView {
config(){
return { view:"datatable", autoConfig:true };
}
init(view){
view.sync(data);
data.waitData.then(() => {
view.select(view.getFirstId());
});
}
}Events
init(view){
data.attachEvent("onAfterLoad", () => {
view.select(view.getFirstId());
});
}Async data: Wait for all
webix.promise.all
import {data} from "models/records";
import {options} from "models/options";
export class DetailsView extends from JetView {
config(){
return { template:"#title#. #category#"};
}
urlChange(view, url){
webix.promise.all([
data.waitData,
options.waitData
]).then(()=>{
let id = url[0].params.id;
let item = webix.copy(data.getItem(id));
item.category = options.getItem(item.categoryId).value;
view.parse(item);
});
}
}Async views: Wait for config
export default class ChartView extends JetView {
config(){
let chart = {
view:"chart", type:"bar",
series:[]
};
return webix.ajax("data/colors").then(function(data){
const colors = data.json();
for(let i in colors){
chart.series.push({
value:"#"+i+"#", color:colors[i]
});
}
return {
rows:[ chart, { template:"Chart description"}]
};
});
}
init(view){
view.queryView({view:"chart"}).load(url);
}
}Async data: Saving
view/collection.waitSave (Webix 6.3+)
//models/records
export const data = new webix.DataCollection({
url:"load/records",
save:"save/records"
});
// views/data
webix.dp(data).attachEvent("onAfterSync", (status, text, data) => {
//webix.message("Data was saved");
});Dataprocessor events
// view
data.waitSave(() => {
data.add({ });
}).then((res) => {
view.select(res.id);
});a single operation
multiple operations
Not Covered Topics
- Jet App inside another Jet App
- Jet App as custom Webix widget
- rebuild app according to changing viewport size
- changing view content
- app-level redirects
Links
Demo: click here
Task for practice: click here
Follow-up text: click here
3-3. Webix Jet: Data
By ihelga
3-3. Webix Jet: Data
Data models. Loading and saving data. Managing async data and config in Webix Jet.
- 562