// setup an App namespace
// This is done to prevent collisions in the global namespace
Ext.ns('App');

/** * App.BookStore * @extends Ext.data.Store * @cfg {String} url This will be a url of a location to load the BookStore * This is a specialized Store which maintains books. * It already knows about Amazon's XML definition and will expose the following * Record defintion: * - Author * - Manufacturer * - ProductGroup * - DetailPageURL */ App.BookStore = function(config) { var config = config || {}; Ext.applyIf(config, { reader: new Ext.data.XmlReader({ // records will have an "Item" tag record: 'Item', id: 'ASIN', totalRecords: '@total' }, [ // set up the fields mapping into the xml doc // The first needs mapping, the others are very basic {name: 'Author', mapping: 'ItemAttributes > Author'}, 'Title', 'Manufacturer', 'ProductGroup', // Detail URL is not part of the column model of the grid 'DetailPageURL' ]) }); // call the superclass's constructor App.BookStore.superclass.constructor.call(this, config); }; Ext.extend(App.BookStore, Ext.data.Store);
/** * App.BookGrid * @extends Ext.grid.GridPanel * This is a custom grid which will display book information. It is tied to * a specific record definition by the dataIndex properties. * * It follows a very custom pattern used only when extending Ext.Components * in which you can omit the constructor. * * It also registers the class with the Component Manager with an xtype of * bookgrid. This allows the application to take care of the lazy-instatiation * facilities provided in Ext's Component Model. */ App.BookGrid = Ext.extend(Ext.grid.GridPanel, { // override initComponent : function() { Ext.apply(this, { // Pass in a column model definition // Note that the DetailPageURL was defined in the record definition but is not used // here. That is okay. columns: [ {header: "Author", width: 120, dataIndex: 'Author', sortable: true}, {header: "Title", dataIndex: 'Title', sortable: true}, {header: "Manufacturer", width: 115, dataIndex: 'Manufacturer', sortable: true}, {header: "Product Group", dataIndex: 'ProductGroup', sortable: true} ], sm: new Ext.grid.RowSelectionModel({singleSelect: true}), // Note the use of a storeId, this will register thisStore // with the StoreMgr and allow us to retrieve it very easily. store: new App.BookStore({ storeId: 'gridBookStore', url: 'sheldon.xml' }), // force the grid to fit the space which is available viewConfig: { forceFit: true } }); // finally call the superclasses implementation App.BookGrid.superclass.initComponent.call(this); } }); // This will associate an string representation of a class // (called an xtype) with the Component Manager // It allows you to support lazy instantiation of your components Ext.reg('bookgrid', App.BookGrid);
/** * App.BookDetail * @extends Ext.Panel * This is a specialized Panel which is used to show information about * a book. * * This demonstrates adding 2 custom properties (tplMarkup and * startingMarkup) to the class. It also overrides the initComponent * method and adds a new method called updateDetail. * * The class will be registered with an xtype of 'bookdetail' */ App.BookDetail = Ext.extend(Ext.Panel, { // add tplMarkup as a new property tplMarkup: [ 'Title: {Title}
', 'Author: {Author}
', 'Manufacturer: {Manufacturer}
', 'Product Group: {ProductGroup}
' ], // startingMarup as a new property startingMarkup: 'Please select a book to see additional details', // override initComponent to create and compile the template // apply styles to the body of the panel and initialize // html to startingMarkup initComponent: function() { this.tpl = new Ext.Template(this.tplMarkup); Ext.apply(this, { bodyStyle: { background: '#ffffff', padding: '7px' }, html: this.startingMarkup }); // call the superclass's initComponent implementation App.BookDetail.superclass.initComponent.call(this); }, // add a method which updates the details updateDetail: function(data) { this.tpl.overwrite(this.body, data); } }); // register the App.BookDetail class with an xtype of bookdetail Ext.reg('bookdetail', App.BookDetail);
/** * App.BookMasterDetail * @extends Ext.Panel * * This is a specialized panel which is composed of both a bookgrid * and a bookdetail panel. It provides the glue between the two * components to allow them to communicate. You could consider this * the actual application. * */ App.BookMasterDetail = Ext.extend(Ext.Panel, { // override initComponent initComponent: function() { // used applyIf rather than apply so user could // override the defaults Ext.applyIf(this, { frame: true, title: 'Book List', width: 540, height: 400, layout: 'border', items: [{ xtype: 'bookgrid', itemId: 'gridPanel', region: 'north', height: 210, split: true },{ xtype: 'bookdetail', itemId: 'detailPanel', region: 'center' }] }) // call the superclass's initComponent implementation App.BookMasterDetail.superclass.initComponent.call(this); }, // override initEvents initEvents: function() { // call the superclass's initEvents implementation App.BookMasterDetail.superclass.initEvents.call(this); // now add application specific events // notice we use the selectionmodel's rowselect event rather // than a click event from the grid to provide key navigation // as well as mouse navigation var bookGridSm = this.getComponent('gridPanel').getSelectionModel(); bookGridSm.on('rowselect', this.onRowSelect, this); }, // add a method called onRowSelect // This matches the method signature as defined by the 'rowselect' // event defined in Ext.grid.RowSelectionModel onRowSelect: function(sm, rowIdx, r) { // getComponent will retrieve itemId's or id's. Note that itemId's // are scoped locally to this instance of a component to avoid // conflicts with the ComponentMgr var detailPanel = this.getComponent('detailPanel'); detailPanel.updateDetail(r.data); } }); // register an xtype with this class Ext.reg('bookmasterdetail', App.BookMasterDetail); // Finally now that we've defined all of our classes we can instantiate // an instance of the app and renderTo an existing div called 'binding-example' // Note now that classes have encapsulated this behavior we can easily create // an instance of this app to be used in many different contexts, you could // easily place this application in an Ext.Window for example Ext.onReady(function() { // create an instance of the app var bookApp = new App.BookMasterDetail({ renderTo: 'binding-example' }); // We can retrieve a reference to the data store // via the StoreMgr by its storeId Ext.StoreMgr.get('gridBookStore').load(); });