Main force

Looking back at our design, the main view is the container for the rest of the UI in our application. It looks like this:

// app/view/main/Main.js
Ext.define('Postcard.view.main.Main', {
    extend: 'Ext.Panel',
    xtype: 'app-main',
    plugins: ['viewport', 'responsive'],
    controller: 'main',
    viewModel: 'main',
    session: true,

    responsiveConfig: {
        'tall': {
            layout: {
                type: 'card'
            }
        },

        'wide': {
            layout: {
                type: 'hbox',
                align: 'stretch'
            }
        }
    },

    dockedItems: [
        { xtype: 'app-header' },
        { 
            dock: 'bottom', xtype: 'button', cls: 'logout', 
            overCls: '', focusCls: '', text: 'Logout'
        }
    ],

    items: [
        { xtype: 'threads', flex: 1 },
        {
            xtype: 'container',
            flex: 1,
            defaults: { hidden: true },
            items: [
                { xtype: 'messages' },
                { xtype: 'composer' }
            ]
        }
    ],

    isCard: function() {
        return this.getLayout().type === 'card';
    }
});

There's a lot going on here, but only a couple of new concepts. Note that we have added a couple of plugins to this class: viewport and responsive. As we didn't let our application auto create a view as a viewport, adding the viewport plugin will do just that. The responsive plugin allows you to use the responsiveConfig option, which we discussed earlier in the chapter.

In this instance, on screens that are tall, that is, higher than they are wide, such as portrait screens, we use a card layout. On screens that are wide, that is, wider than they are high, we use an hbox layout because there's a lot more horizontal space. This simple declarative way of setting up a responsive view has allowed us to make very distinct changes to our application with only a few lines of configuration.

We've added a utility method to this view to help with manipulating our responsive setup; the isCard view will let us neatly determine whether this view is using a card layout or hbox layout.

Tip

Syntactic sugar is an alternative way of writing something that makes it easier to read or allows it to better express its intent. The isCard method is an example of this, not strictly necessary, but it makes the calling code shorter and easier to understand.

The rest of this configuration should be very familiar: two dockedItems, one is the application header view and another supplying a logout button, and the three other views of this application in the items array.

Main ViewModel

On first glance, the code for this will look pretty standard, but when you look back at the code for the main view itself, you notice that currentTag or searchTerm is not going to be used anywhere. So, why define them if they're not going to be used? Refer to ViewModel in the following code:

// app/view/main/MainModel.js
Ext.define('Postcard.view.main.MainModel', {
    extend: 'Ext.app.ViewModel',
    alias: 'viewmodel.main',

    data: {
        currentTag: 'Inbox',
        searchTerm: null
    }
});

In Ext JS, we have the concept of parent and child view models. The main view model, configured on the main view, will become available to all child components of the main view. This means that subviews can get data on the main view and also pass information back up to it. This is a fantastic way of passing data between two child components.

Main ViewController

Refer to ViewController in the following code:

// app/view/main/MainController.js
Ext.define('Postcard.view.main.MainController', {
    extend: 'Ext.app.ViewController',
    alias: 'controller.main',

    routes: {
        'thread/new': 'showRightPane',
        'thread/:id/messages': 'showRightPane',
        'thread/:id/messages/new': 'showRightPane'
    },

    listen: {
        component: {
            'button[cls="logout"]': {
                click: function() {
                    window.localStorage.removeItem('loggedin'),
                    window.location = '/';
                }
            }
        }
    },

    showRightPane: function(id) {
        if(this.getView().isCard()) {
            this.getView().setActiveItem(1);
        }
    }
});

The most interesting thing happening in here is the route handlers; we're giving several routes to the showRightPane handler. Looking back at our examination of user flow and routes in our application, many of the routes need us to ensure that the right-hand panel is in view. This only applies to the responsive portrait view, so we only change the active panel if the portrait view's card layout is available.

The interesting part is that we've got route handlers that only do part of what we'd expect. Where are the bits that pass IDs and show subviews? Don't worry, we'll revisit this shortly.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset