0
votes

I am trying to learn ExtJS 5, and have run into a problem already, trying to slice up my UI into appropriate views and viewControllers. My application consists of a single file with a border layout split into three sections. I'd like to turn each section into a seperate module, but I am not sure the correct way to do that. I tried simply adding a Controller and View, and changing the xtype of the item to the xtype of the view but I just got an empty panel.

The "south" part of the border layout is what I am trying to move to its own controller, to start.

Here is a slimmed down version of my application:

Ext.define('RpgInfoSystem.Application', {
    extend: 'Ext.app.Application',
    name: 'RpgInfoSystem',
    launch: function() {
        Ext.create('Ext.container.Viewport', {
            layout: 'border',
            bodyBorder: false,
            defaults: {
                collapsible: true,
                split: true,
                bodyPadding: 5
            },
            // Here is where we require our modules
            //requires: ['RpgInfoSystem.Reference.controller.Reference'],
            // Here is where we insert our modules into the UI
            items: [{
                region: 'north',
                xtype: 'component',
                collapsible: false,
                resizeable: false,
                floatable: false,
                padding: 0,
                margin: 0,
                height: 25,
                minHeight: 25,
                maxHeight: 25,
                html: '<h1 style="margin: 0; padding: 0;">RPG Information System</h1>'
            }, {
                xtype: 'tabpanel',
                collapsible: false,
                region: 'center',
                margin: '5 0 0 0',
                items: [{
                    title: 'Initiative Tracker',
                    html: '<h2>Main Page</h2><p>This is where the main content will go. For players, this will be their character sheets. For the DM, this will be the initiative tracker.</p>'
                }, {
                    title: 'Templates',
                    html: 'Templates for NPCs and enemies, which can be copied into the initiative tracker.'
                }]
            }, {
                title: 'Utilities',
                xtype: 'panel',
                region: 'east',
                floatable: false,
                margin: '5 0 0 0',
                width: 300,
                minWidth: 100,
                //maxWidth: 250,
                layout: {
                    type: 'vbox',
                    pack: 'start',
                    align: 'stretch'
                },
                items: [{
                    title: 'Campaign Info',
                    xtype: 'tabpanel',
                    flex: 1,
                    margin: '0 0 1 0',
                    items: [{
                            title: 'Session',
                            html: 'A text area to enter notes for the campaign and scroll through other users\'s notes.'
                        }, {
                            title: 'Campaign',
                            html: 'Information about the current campaign, as well as the ability to take and edit notes.'
                        }
                    ]
                }]
            }, {
                title: 'Reference',
                xtype: 'mycustomview', //HERE IS WHERE I AM CUSTOMIZING
                region: 'south',
                floatable: false,
                height: 250,
                minHeight: 150,
                collapsed: true,
            }]
        });
    }
});

And my launcher:

Ext.application({
    name: 'RpgInfoSystem',
    extend: 'RpgInfoSystem.Application',
    controllers: [
        'Reference'
    ]
});
2

2 Answers

0
votes

Just create two files for each 'section'

In, Section1.js (goes in views/Section1.js)

Ext.define('RpgInfoSystem.view.Section1', {    
    extend: 'Ext.Component',
    alias: 'widget.Section1',
    itemId: 'Section1',
    region: 'north',
    collapsible: false,
    resizeable: false,
    floatable: false,
    padding: 0,
    margin: 0,
    height: 25,
    minHeight: 25,
    maxHeight: 25,
    html: '<h1 style="margin: 0; padding: 0;">RPG Information System</h1>'
});

Then you need to create the controller for this section (goes in controller/Section1.js):

Ext.define('RpgInfoSystem.controller.Section1', {
    extend: 'Ext.app.Controller',
    views: ['Section1']
    ....
});

And in items of your viewport:

items: [Ext.widget('Section1'), Ext.widget('Section2')] //and so on

And in the Application.js file make sure you have these config options:

views: ['RpgInfoSystem.view.Section1', 'RpgInfoSystem.view.Section2'],
controllers: ['RpgInfoSystem.controller.Section1', 'RpgInfoSystem.controller.Section2']

You can do this for every UI element, although I don't know at which point it becomes overdoing it as I am not an expert either.

Have not tried V5 yet, but that's probably helpful

http://www.sencha.com/blog/ext-js-5-mvc-mvvm-and-more

0
votes

At first you need to create your widgets in separate files. Also pay attention for names, so if your application called RpgInfoSystem and your widget called Section1 you need to create Section1.js file in view directory under application root. If sub-folders used their names should be included into the name of your class(example - RpgInfoSystem.view.Panel1.Section1). Thats actually about why Ext could try to load unexisted files. Also the key moment that you should understand difference between view controllers and regular one(that've been in ExtJs4 and remain in 5th one). Regular one are listening to the events, while view controller is more line "bunch of functions" which could be called from view. I didn't find any recommendations about where to place view models and view controllers at least its not declared as rule so you can place it anywhere you want. I prefer to create them near the widgets that are related to them(so i have three classes (and files appropriate) - widget(RpgInfoSystem.view.Section1), model (RpgInfoSystem.view.Section1Model) and controller (RpgInfoSystem.view.Section1Controller)). Next - suppose the best way to use components and widgets in panels is xtype system(if you'll dive deeper you'll also find ptype for plugin and ftype for features, but its don't needed for now). So you'll have next structure and code for your tabs panel: In ~/view/InitiativeTabs.js:

Ext.define(
    "RpgInfoSystem.view.InitiativeTabs",
    {
        requires: [
            "RpgInfoSystem.view.InitiativeTabsController",
            "RpgInfoSystem.view.InitiativeTabsModel"
        ],

        controller: "initiativetabsctrl",
        viewModel: "initiativetabsmodel",

        extend: 'Ext.tab.Panel', // this correspond for the xtype: 'tabpanel'
        alias: 'widget.initiativeTabs', // this would define xtype for THIS widget

        items: [{
            title: 'Initiative Tracker',
            html: '<h2>Main Page</h2><p>This is where the main content will go. For players, this will be their character sheets. For the DM, this will be the initiative tracker.</p>'
        }, {
            // suppose this would go into separate file too when would became a widget
            title: 'Templates',
            html: 'Templates for NPCs and enemies, which can be copied into the initiative tracker.',
            listeners: {
                render: 'someRandomFn' // call function from our controller
            }
        }]}
);

In ~/view/InitiativeTabsController.js:

Ext.define("RpgInfoSystem.view.InitiativeTabsController",{
    extend : 'Ext.app.ViewController',
    alias: 'controller.initiativetabsctrl', // this allows to use our view controller in hm... view:)

    someRandomFn: function(){
        alert("some random fn called");
    }
});

In ~/view/InitiativeTabsModel.js:

Ext.define(
    "RpgInfoSystem.view.InitiativeTabsModel",
    {
        extend: "Ext.app.ViewModel",

        alias: "viewmodel.initiativetabsmodel",
    }
);

And finally your app:

Ext.define('RpgInfoSystem.Application', {
    extend: 'Ext.app.Application',
    name: 'RpgInfoSystem',
    launch: function() {
        Ext.create('Ext.container.Viewport', {
            layout: 'border',
            bodyBorder: false,
            defaults: {
                collapsible: true,
                split: true,
                bodyPadding: 5
            },
            // Here is where we require our modules
            //requires: ['RpgInfoSystem.Reference.controller.Reference'],
            // Here is where we insert our modules into the UI
            items: [{
                region: 'north',
                xtype: 'component',
                collapsible: false,
                resizeable: false,
                floatable: false,
                padding: 0,
                margin: 0,
                height: 25,
                minHeight: 25,
                maxHeight: 25,
                html: '<h1 style="margin: 0; padding: 0;">RPG Information System</h1>'
            }, {
                xtype: 'initiativetabs',
                collapsible: false, // this thee configs are related to the widget config in parent panel,
                region: 'center',  //  so for widget independence purposes 
                margin: '5 0 0 0', // suppose they must be here
            }, {
                title: 'Utilities',
                xtype: 'panel',
                region: 'east',
                floatable: false,
                margin: '5 0 0 0',
                width: 300,
                minWidth: 100,
                //maxWidth: 250,
                layout: {
                    type: 'vbox',
                    pack: 'start',
                    align: 'stretch'
                },
                items: [{
                    title: 'Campaign Info',
                    xtype: 'tabpanel',
                    flex: 1,
                    margin: '0 0 1 0',
                    items: [{
                            title: 'Session',
                            html: 'A text area to enter notes for the campaign and scroll through other users\'s notes.'
                        }, {
                            title: 'Campaign',
                            html: 'Information about the current campaign, as well as the ability to take and edit notes.'
                        }
                    ]
                }]
            }, {
                title: 'Reference',
                xtype: 'mycustomview', //HERE IS WHERE I AM CUSTOMIZING
                region: 'south',
                floatable: false,
                height: 250,
                minHeight: 150,
                collapsed: true,
            }]
        });
    }
});

Also see extjs examples to understand binding http://dev.sencha.com/ext/5.0.0/examples/kitchensink/#data-binding