Layouting Question

I’m used to ExtJS and currently evaluate webix.js for a new project.

Since i’m trying to setup a webix-js app with MVV-pattern, i use requireJS to separate views from controls and make my code reusable.

That’s why i’m used to create the entire layout by framework and not to use any HTML-Target Containers. I also want to avoid using ids for my layout elements, because i want to be possible to create multiple instances of certains ui-elements without having to override any predefined ids.

My preferred way of creating a layout would be (see comments):

`
define('app/main', [
    'webix',
    'app/ui/table', // contains conf-obj for a table, no logic
    'app/ui/form' //  contains conf-obj for a form, no logic
], function (
    webix,
    tableConf,
    formConf
) {
    return function () {
        /* create instances of form and table
         * table and form receive autogenerated ids that I don't care about, because i have
         * a reference to both instances
         */
        var table = webix.ui(tableConf),
            form = webix.ui(formConf);
    
        /* create layout and embed instances */
        return webix.ui({
            id: 'main',
            rows: [table, form] // THIS IS NOT WORKING, BUT I WISH IT DID
        });
        
        /* do any sort of logic/bindings etc.
         */
        table.attachEvent('onSelectChange', function () { /* do something */});
    }
});


/* launch app */
main();
`

But this is how I’m currently forced to do it.

`
define('app/main', [
    'webix',
    'app/ui/table', // contains conf-obj for a table, no logic
    'app/ui/form' //  contains conf-obj for a form, no logic
], function (
    webix,
    tableConf,
    formConf
) {
    return function () {
        var layout, form, table;
    
        /* create layout */
        layout = webix.ui({
            id: 'main',
            rows: [tableConf, formConf] // THIS IS WORKING
        });
        
        /* form and table have autogenerated ids, that i don't know, i also don't have a reference
         * tableConf.id and formConf.id are empty
         */
        form = $$('main').$$('$form1'); // i need to guess the selector for the webix-obj-reference to my form
        table = $$('main').$$('$table1');
        
        /* do any sort of logic/bindings etc. */
        table.attachEvent('onSelectChange', function () { /* do something */});
        
        return layout;
    }
});


/* launch app */
main();
`

I possibly just don’t get the concept of it, so please help. What’s the best webix-pattern of structuring an app?

i also figured out a way of adding elements to my layout AFTER it’s initialization BUT this only works for very simple layouts.

`

define('app/main', [
    'webix',
    'app/ui/table',
    'app/ui/form'
], function (
    webix,
    tableConf,
    formConf
) {
    return function () {
        var layout, form, table;
    
        /* create layout */
        layout = webix.ui({
            id: 'main',
            rows: [] // init empty layout
        });
        
        form = webix.ui(formConf);
        table = webix.ui(tableConf);
        
        /* this works, but if my base layout is more complex, this won't work */
        layout.addView(form);
        layout.addView(table);
        
        
        /* do any sort of logic/bindings etc. */
        table.attachEvent('onSelectChange', function () { /* do something */});
        
        return layout;
    }
});


/* launch app */
main();

`

I’d really appreciate ideas for better building/structuring webix-apps. Thanks in advance!

Hi,

A solution with addView can be used to create a layout of any complexity, but it is a bit performance expensive, you will not want to use it for complex layouts. Instead of it, you can use isolated views, check the next code

define('app/main', [
    'webix',
    'app/ui/table', // contains conf-obj for a table, no logic
    'app/ui/form' //  contains conf-obj for a form, no logic
], function (
    webix,
    tableConf,
    formConf
) {
    return function () {

        var view = webix.ui({
            id: 'main',
            isolate:true,
            rows: [tableConf, formConf]
        });
        
        /* do any sort of logic/bindings etc.
         */
        view.$$(tableConf.id).attachEvent('onSelectChange', function () { /* do something */});

        return view;
    }
});

Here, I have added isolate:true to the config of layout, which guaranty that all IDs in the layout will be isolated and will not be globally accessible, instead of $$ command, I can use view.$$ to access inner elements by their ID.

Also, in above case it may have sense to define the event handler for table widget in the app/ui/table file. You can use on property in the config object to embed event handler in the config.

I think i got it. Thanks.

I was hoping for a way to avoid having to define “subview”-ids in some way, but now I’ll go for isolated subviews.

My loaded config files won’t contain any ids, so i have to assign ids when using the objects - just to be able to select them for further bindings.

define('app/main', [
    'webix',
    'app/ui/table', // contains conf-obj for a table, no logic
    'app/ui/form' //  contains conf-obj for a form, no logic
], function (
    webix,
    tableConf,
    formConf
) {
    return function (viewId) {
 
        var view = webix.ui({
            id: viewId,
            isolate:true,
            rows: [
                   webix.extend({ id: 'maintable' }, tableConf),
                   webix.extend({ id: 'mainform' }, formConf)
            ]
        });

        view.$$('maintable').attachEvent('onSelectChange', function () { /* do something */});
        view.$$('mainform').attachEvent('onSomeEvent', function () {});
 
        return view;
    }
});

Maybe there will be a nicer way for this in the future. Until then I’ll have to get used to it :wink:

But thanks for the help so far :slight_smile:

PS: edited syntax highlighting