A basket case

The cart itself is a grid showing the products in the cart and the quantity of each. It's enclosed in a window with a couple of action buttons at the bottom as follows:

// app/view/cart/Cart.js
Ext.define('Alcohology.view.cart.Cart', {
    extend: 'Ext.Window',
    requires: ['Alcohology.view.cart.CartController'],
    controller: 'cart',
    width: 500,
    height: 350,
    modal: true,
    resizable: false,
    header: false,
    onEsc: Ext.emptyFn,
    layout: 'fit',
    items: [
        {
            xtype: 'grid',
            bind: '{cart}',
            plugins: {
                ptype: 'cellediting',
                clicksToEdit: 1
            },
            listeners: {
                edit: function(editor, e) {
                    e.record.commit();
                }
            },
            hideHeaders: true,
            emptyText: 'No items in the cart.',
            columns: [
                { name: 'Product', dataIndex: 'productName', flex: 1 },
                {
                    name: 'Quantity', dataIndex: 'quantity',
                    editor: {
                        xtype: 'numberfield',
                        allowBlank: false
                    }
                }
            ]
        }
    ],
    bbar: [
        '->',
        { text: 'Close', itemId: 'closeCart' },
        { text: 'Order Now', itemId: 'orderNow' }
    ]
});

Within the grid, we have used the cellediting plugin that allows the user to tap the quantity column and use the plus or minus icons that Ext JS provides on the touch-friendly theme to adjust the item quantity. When the quantity is edited and the edit event fires on the grid, we immediately commit the change to the cart store, which is bound to the grid from the parent view model.

Note that there is no specific view model for this view. Instead, as we instantiated this window within the constructor of the main view, it'll inherit the main view model. This means that we can share the cart store with multiple components by having it high up in the view model hierarchy.

Let's move on to the cart view controller, as shown in the following code:

// app/view/cart/CartController.js
Ext.define('Alcohology.view.cart.CartController', {
    extend: 'Ext.app.ViewController',
    alias: 'controller.cart',
    listen: {
        component: {
            '#closeCart': { click: 'onCartClose' },
            '#orderNow': { click: 'onOrderNow' }
        }
    },

    onCartClose: function() {
        this.getView().hide();
    },

    onOrderNow: function() {
        var vm = this.getViewModel();

        if(!vm.get('currentUser')) {
            this.fireEvent('loginrequired'),
        } else {
               var order = vm.get('cart').toOrder();

            vm.get('cart').removeAll();
            vm.get('orders').add(order);

            Ext.toast('Order Accepted!'),

            this.getView().hide();
        }
    }
});

We wire up event handlers for the window's buttons by using itemId, which we defined in the view as the selector. The onCartClose method is straightforward, but the onOrderNow one is a little more interesting.

It first determines if the user is logged in by checking whether currentUser on the view model is null. If the user is not logged in, a loginrequired event will be fired; if you remember, we handled this earlier in the main view controller. If the user is logged in, we perform the following actions:

  • Call the toOrder method from the cart store to get an Order model
  • Remove all the items from the cart
  • Add the new Order model to the orders store on the view model
  • Show a toast notification to the user
  • Hide the cart window

All of this results in the cart being moved to an order. In a comprehensive e-commerce application, this is the bit that will be replaced by credit card capturing and payment processing, but we've taken the simple approach here, that is, composing various calls to other classes to perform the action we need.

As previously discussed, the cart view doesn't have its own view model because it inherits from its parent, so we'll now move on to the final view in the application; the account window.

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

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