Ext.require([ 'Ext.data.*', 'Ext.panel.Panel', 'Ext.layout.container.Card', 'Ext.tip.QuickTipManager' ]); Ext.define('Customer', { extend: 'Ext.data.Model', fields: [{ name: 'id', type: 'int' }, 'name', 'phone'], associations: [{ model: 'Order', type: 'hasMany', autoLoad: true }], proxy: { type: 'ajax', url: 'customer.php' } }); Ext.define('Order', { extend: 'Ext.data.Model', fields: [{ name: 'id', type: 'int' },{ name: 'customer_id', type: 'int' },{ name: 'date', type: 'date', dateFormat: 'Y-m-d' }], belongsTo: 'Customer', associations: [{ model: 'OrderItem', type: 'hasMany', autoLoad: true }], proxy: { type: 'ajax', url: 'order.php' } }); Ext.define('OrderItem', { extend: 'Ext.data.Model', fields: [{ name: 'id', type: 'int' }, { name: 'order_id', type: 'int' },'product', { name: 'quantity', type: 'int' }, { name: 'price', type: 'float' }], belongsTo: 'Order', proxy: { type: 'ajax', url: 'orderitem.php' } }); Ext.define('CustomerGrid', { extend: 'Ext.grid.Panel', alias: 'widget.customergrid', title: 'Customers', initComponent: function(){ Ext.apply(this, { store: { autoLoad: true, model: 'Customer', listeners: { load: function() { Logger.log('Customer store loaded', false); } } }, columns: [{ text: 'Id', dataIndex: 'id' },{ text: 'Name', dataIndex: 'name', flex: 1 }, { text: 'Phone', dataIndex: 'phone' }], dockedItems: [{ xtype: 'toolbar', items: { itemId: 'load', text: 'Load Orders', scope: this, handler: this.loadOrders, disabled: true } }] }); this.callParent(); this.getSelectionModel().on('selectionchange', this.onSelectChange, this); }, onSelectChange: function(selModel, selections) { this.active = selections[0]; this.down('#load').setDisabled(!this.active); }, loadOrders: function(){ var rec = this.active, name = rec.get('name'), owner = this.ownerCt, orders; orders = rec.orders(); if (orders.isLoading()) { Logger.log('Begin loading orders: ' + rec.getId(), true); } orders.on('load', function(){ Logger.log('Order store loaded - ' + rec.getId(), false); }); owner.add({ title: 'Orders - ' + rec.getId(), customer: rec, xtype: 'ordergrid', store: orders }); owner.getLayout().next(); } }); Ext.define('OrderGrid', { extend: 'Ext.grid.Panel', alias: 'widget.ordergrid', initComponent: function(){ Ext.apply(this, { columns: [{ text: 'Id', dataIndex: 'id' },{ flex: 1, text: 'Date', dataIndex: 'date', renderer: Ext.util.Format.dateRenderer('Y-m-d') }], dockedItems: [{ xtype: 'toolbar', items: [{ text: 'Back', scope: this, handler: this.onBackClick },{ itemId: 'load', text: 'Load Order Items', scope: this, handler: this.loadItems, disabled: true }] }] }); this.callParent(); this.getSelectionModel().on('selectionchange', this.onSelectChange, this); }, onBackClick: function(){ this.ownerCt.getLayout().prev(); this.destroy(); }, onSelectChange: function(selModel, selections) { this.active = selections[0]; this.down('#load').setDisabled(!this.active); }, loadItems: function(){ var customerName = this.customer.get('name'), rec = this.active, date = Ext.Date.format(rec.get('date'), 'Y-m-d'), owner = this.ownerCt, orderitems; orderitems = rec.orderitems(); if (orderitems.isLoading()) { Logger.log('Begin loading order items - ' + rec.getId(), true); } orderitems.on('load', function(){ Logger.log('Order items loaded - ' + rec.getId(), false); }); owner.add({ title: 'Order Items - ' + rec.getId(), xtype: 'orderitemgrid', store: orderitems }); owner.getLayout().next(); } }); Ext.define('OrderItemGrid', { extend: 'Ext.grid.Panel', alias: 'widget.orderitemgrid', initComponent: function(){ Ext.apply(this, { columns: [{ text: 'Id', dataIndex: 'id' },{ flex: 1, text: 'Product', dataIndex: 'product' }, { text: 'Quantity', dataIndex: 'quantity' }, { text: 'Price', dataIndex: 'price', renderer: Ext.util.Format.usMoney }], dockedItems: [{ xtype: 'toolbar', items: [{ text: 'Back', scope: this, handler: this.onBackClick }, { itemId: 'load', text: 'Parent association loader', tooltip: 'Demonstrate loading parent relationships - A new record will be created so we ignore any previous associations setup', scope: this, handler: this.onLoadClick, disabled: true }] }] }); this.callParent(); this.getSelectionModel().on('selectionchange', this.onSelectChange, this); }, onSelectChange: function(selModel, selections) { this.active = selections[0]; this.down('#load').setDisabled(!this.active); }, onBackClick: function(){ this.ownerCt.getLayout().prev(); this.destroy(); }, onLoadClick: function(){ var rec = this.active, id = rec.getId(); new ItemLoader({ width: 400, height: 400, modal: true, title: this.title.replace('Order Items', 'Order Item ' + id), orderItemData: rec.data, orderItemId: id }).show(); } }); Ext.define('ItemLoader', { extend: 'Ext.window.Window', initComponent: function(){ Ext.apply(this, { border: false, autoScroll: true, dockedItems: [{ xtype: 'toolbar', items: [{ text: 'Print order detail', scope: this, handler: this.onOrderClick }, { itemId: 'company', text: 'Print company detail', disabled: true, scope: this, handler: this.onCompanyClick }] }], bodyPadding: 5, tpl: '
{type} {id} - {value}
', tplWriteMode: 'append' }); this.callParent(); this.orderItem = new OrderItem(this.orderItemData, this.orderItemId); }, onOrderClick: function(){ var id = this.orderItem.get('order_id'), hasOrder = !!this.order; if (!hasOrder) { Logger.log('Begin loading order - ' + id, true); } this.orderItem.getOrder({ scope: this, success: function(order){ this.order = order; this.down('#company').enable(); if (!hasOrder) { Logger.log('Order loaded - ' + id, false); } this.update({ type: 'Order', id: order.getId(), value: Ext.Date.format(order.get('date'), 'Y-m-d') }); } }); }, onCompanyClick: function(){ var id = this.order.get('customer_id'), hasCustomer = !!this.customer; if (!hasCustomer) { Logger.log('Begin loading customer - ' + id, true); } this.order.getCustomer({ scope: this, success: function(customer){ this.customer = customer; if (!hasCustomer) { Logger.log('Customer loaded - ' + id, false); } this.update({ type: 'Customer', id: customer.getId(), value: customer.get('name') }); } }); } }); Logger = (function(){ var panel; return { init: function(log){ panel = log; }, log: function(msg, isStart){ panel.update({ now: new Date(), cls: isStart ? 'beforeload' : 'afterload', msg: msg }); panel.body.scroll('b', 100000, true); } }; })(); Ext.onReady(function(){ var main = Ext.create('Ext.panel.Panel', { renderTo: document.body, width: 750, height: 400, border: false, layout: { type: 'vbox', align: 'stretch' }, items: [{ height: 200, xtype: 'container', layout: 'card', margin: '0 0 5 0' }, { flex: 1, title: 'Loader log', tplWriteMode: 'append', tpl: '
[{now:date("H:i:s")}] - {msg}
', bodyPadding: 5, autoScroll: true, listeners: { render: Logger.init } }] }); Logger.log('Begin loading customer store', true); main.items.first().add({ xtype: 'customergrid' }); });