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