Docs
Big demos
Starter
Samples
clone the demo app
git clone https://github.com/webix-hub/jet-startinstall toolchain and start the app
cd jet-start
yarn install
yarn startopen app in the browser
http://localhost:8080cd jet-start
npm install
npm startcheck code quality
yarn lintget files for deploy
yarn buildWebpack's Magic
npm run lintnpm run build/sources/myapp.js
/ sources/views
/sources/models
/sources/locales
/sources/styles
- app's config
- UI chunks
- data and data related logic
- localization
- css, images, etc.
import {JetApp, EmptyRouter, HashRouter } from "webix-jet";
export default class MyApp extends JetApp{
constructor(config){
const defaults = {
id : APPNAME,
version : VERSION,
router : BUILD_AS_MODULE ? EmptyRouter : HashRouter,
debug : !PRODUCTION,
start : "/top/start"
};
super({ ...defaults, ...config });
}
}
if (!BUILD_AS_MODULE){
webix.ready(() => new MyApp().render() );
}some.com#!/top/start
some.com/#!/top/start
some.com/#!/top/data
views
some.com/#!/top/details.form
some.com/#!/details.template
models
export default {
template:"Start page"
};
import {JetView} from "webix-jet";
export default class TopView extends JetView {
config(){
return {
cols:[
{ view:"menu" },
{ template:"Something here"}
]
};
}
}/views/start.js
/views/top.js
Objects
Classes
import {JetView} from "webix-jet";
import {data} from "models/records";
export default class DataView extends JetView {
config(){
return { rows:[
{ view:"toolbar" },
{ view:"datatable", autoConfig:true }
]};
}
init(view){
view.queryView("datatable").parse(data);
}
}/views/data.js
Import modules
Composable blocks
Error resistant
Code reusage
Simple
Lifetime handlers
Custom methods
Local variables
Extending
Brief
import {JetView} from "webix-jet";
import {data} from "models/menu";
export default class TopView extends JetView {
config(){
return {
cols:[
{ view:"menu" },
{ template:"Something here"}
]
};
}
init(view){
view.queryView("menu").parse(data);
}
}/views/top.js
import Toolbar from "views/toolbar";
export default class Bottombar extends Toolbar {
init(view){
view.queryView("label").hide();
}
} import {JetView} from "webix-jet";
export default class Toolbar extends JetView {
config(){
return {
view:"toolbar", height:50, elements:[
{ view:"label", label:"My First App!"},
{ },
{ view:"button", autowidth:true, value:"Click me"}
]
};
}
}/views/toolbar.js
/views/bottombar.js
import {JetView} from "webix-jet";
export default class Toolbar extends JetView {
config(){
return {
view:"toolbar", height:50, elements:[
{ view:"button", autowidth:true, value:"Click me",
click:() => this.doClick("Clicked")
}
]
};
}
init(){
//custom properties
this._counter = 0;
}
//custom methods
doClick(message){
this._counter++;
webix.message(message+" "+this._counter);
}
}* this points to Toolbar class here
import {JetView} from "webix-jet";
export default class Toolbar extends JetView {
config(){
return {
view:"toolbar", height:50, elements:[
{ view:"button", autowidth:true, value:"Show some",
click:() => this.app.show("/top/data");
}
]
};
}
} import {JetView} from "webix-jet";
export default class Toolbar extends JetView {
config(){
return { view:"toolbar", elements:[ ... ]};
}
} import Toolbar from "views/toolbar";
export default class TopView extends JetView {
config(){
return { rows:[
Toolbar,
{ cols:[
{ view:"menu" }, {}
]}
]};
}
}/views/toolbar.js
/views/top.js
Static subviews:Class or Object
/views/toolbar.js
/views/top.js
Static subviews: Extra properties
import {JetView} from "webix-jet";
export default class Toolbar extends JetView {
config(){
return { view:"toolbar", elements:[ ... ]};
}
} import Toolbar from "views/toolbar";
export default class TopView extends JetView {
config(){
return { rows:[
{ $subview: Toolbar}, // id, name, etc.
{ cols:[
{ view:"menu" }, {}
]}
]};
}
}/views/toolbar.js
/views/top.js
Static subviews: Extra Properties
import {JetView} from "webix-jet";
export default class Toolbar extends JetView {
config(){
return { view:"toolbar", elements:[ ... ]};
}
} export default class TopView extends JetView {
config(){
return { rows:[
{ $subview: "toolbar"}, // "views/toolbar" will be loaded
{ cols:[
{ view:"menu" }, {}
]}
]};
}
} export default {
template:"Start page"
};
/views/start.js
/views/top.js
Dynamic subviews
/views/data.js
export default {
template:"Data page"
};
import Toolbar from "views/toolbar";
export default class TopView extends JetView {
config(){
return { rows:[
Toolbar,
{ cols:[
{ view:"menu" },
{ $subview:true}
]}
]};
}
} export default {
template:"Start page"
};
/views/start.js
/views/top.js
some.com/#!/top/start
some.com/#!/top/data
export default {
template:"Data page"
};
/views/data.js
import Toolbar from "views/toolbar";
export default class TopView extends JetView {
config(){
return { rows:[
Toolbar,
{ cols:[
{ view:"menu" },
{ $subview:true}
]}
]};
}
}some.com/#!/top/data
some.com/#!/top/top/data
some.com/#!/data
some.com/#!/top
import {JetView} from "webix-jet";
export default class WindowsView extends JetView {
config(){
return {
view:"button", width:200, value:"Popup",
click:() => this._webixPopup.show()
}};
}
init(){
this._webixPopup = webix.ui({
view:"window"
});
}
destroy(){
this._webixPopup.close();
}
}Create with webix.ui()
Not recommended way
import {JetView} from "webix-jet";
import PopupView from "views/windows/popup";
export default class WindowsView extends JetView {
config(){
return {
view:"button", width:200, value:"Popup",
click:() => this._jetPopup.showWindow()
};
}
init(){
this._jetPopup = this.ui(PopupView);
}
}Create with JetView.ui()
Recommended way
import {JetView} from "webix-jet";
export default class PopupView extends JetView {
config(){
return { view:"window" };
}
showWindow() {
this.getRoot().show();
}
}/views/windows/popup.js
/views/toolbar.js
import {JetView} from "webix-jet";
import PopupView from "views/windows/popup";
export default class ToolbarView extends JetView {
config(){
return {
view:"button", width:200, value:"Show popup",
click:() => this._jetPopup.showWindow()
};
}
init(){
this._jetPopup = this.ui(PopupView);
}
}*JetView.getRoot() - access to a top Webix view within the module
/views/griddata.js
import {JetView} from "webix-jet";
import GridView from "views/gridview";
import data1 from "models/data1";
import data2 from "models/data2";
export default class GridData extends JetView {
config(){
return {
rows:[
//embed directly
new GridView(this.app,"", data1),
//or wrap in { $subview: }
{ $subview: new GridView(this.app,"", data2) }
]
}
}
}Re-use modules with
import {JetView} from "webix-jet";
export default class GridView extends JetView {
constructor(app, name, data){
super(app, name); //call parent constructor
this._gridData = data; //define specific parameters
}
config(){
//reuse config
return {
rows:[ toolbar, datatable ]
};
}
init(view) {
//parse specific data
view.queryView("datatable").parse(this._gridData);
}
}/views/gridview.js
Re-use modules with
export default class Toolbar extends JetView {
config(){
return {
view:"button", value:"Click me",
click:() => this.doClick("Clicked")
};
}
doClick(message){
webix.message(message);
}
} export default class Toolbar extends JetView {
config(){
return {
view:"button", value:"Click me", click:function(){
this.$scope.doClick("Clicked");
}
};
}
doClick(message){
webix.message(message);
}
}this
this.$scope
//views/toolbar.js
export default class Toolbar extends JetView {
config(){
return { view:"toolbar" };
}
init(){
console.log(this.getParentView());
}
} //views/top.js
import Toolbar from "views/toolbar";
export default class TopView extends JetView {
config(){
return { rows:[
{ $subview:Toolbar, name:"top-toolbar"}
]};
}
ready(view){
console.log(this.getSubView("top-toolbar"));
}
}.getParentView()
.getSubView()
Don't overuse these methods: module logic should be encapsulated!
import Toolbar from "views/toolbar";
import Bottombar from "views/bottombar";
import {data} from "models/menu";
export default class TopView extends JetView {
config(){
return { rows:[
Toolbar,
{ cols:[
{ view:"menu", localId:"top:menu"} //or id:"top:menu"
]},
Bottombar
]};
}
init(view){
//searching for views
view.queryView("menu").parse(data);
view.queryView("button", "all").forEach((obj) => {
obj.hide();
});
//accessing particular view
this.$$("top:menu").parse(data);
}
doClick(){
// access to top Webix view within the module
this.getRoot()
}
}import "./styles/app.less"; //! stylesheets
import "webix/appbutton"; //! custom widgets
import {JetApp, plugins, HashRouter } from "webix-jet";
export default class MyApp extends JetApp{
constructor(config){
const defaults = {
id : APPNAME, version : VERSION,
router : HashRouter,
debug : !PRODUCTION,
start : "/top/start"
};
super({ ...defaults, ...config });
}
}
webix.ready(() => {
if (webix.CustomScroll && !webix.env.touch) //! App-level Webix logic
webix.CustomScroll.init();
const app = new MyApp();
app.use(plugins.Locale); //! App-level Jet plugins
app.render();
Include:
Use:
export default class MyApp extends JetApp{
constructor(config){
const defaults = {
id: APPNAME, version: VERSION,
start: "/top/start"
debug: true // console.log and debugger on error
};
super({ ...defaults, ...config });
}
}
const app = new MyApp();
app.render();
app.attachEvent("app:error:resolve", function(err, url) {
webix.delay(() => app.show("/top/start"));
});Events:
reuse similar views
don’t address views from other modules by ids
ensure that data is loaded before working with it
Safe developing
Wise developing
Task for practice:
Demo:
Follow-up text: click here