/** * The Row Expander plugin provides an "expander" column to give the user the ability to show * or hide the {@link Ext.grid.Row#cfg!body body} of each row. * * ```javascript * @example({ framework: 'extjs' }) * var store = Ext.create('Ext.data.Store', { * fields: ['fname', 'lname', 'talent', 'powers'], * groupField: 'powers', * data: [ * { 'fname': 'Barry', * 'lname': 'Allen', * 'talent': 'Speedster', * 'powers': true * }, * { 'fname': 'Oliver', * 'lname': 'Queen', * 'talent': 'Archery', * 'powers': false * }, * { 'fname': 'Kara', * 'lname': 'Zor-El', * 'talent': 'All', * 'powers': true * }, * { 'fname': 'Helena', * 'lname': 'Bertinelli', * 'talent': 'Weapons Expert', * 'powers': false * }, * { 'fname': 'Hal', * 'lname': 'Jordan', * 'talent': 'Willpower', * 'powers': true * }, * ] * }); * * Ext.create('Ext.grid.Grid', { * title: 'DC Personnel', * grouped: true, * store: store, * plugins: { * rowexpander: true * }, * itemConfig: { * body: { * tpl: '<img height="100" src="http://www.sencha.com/assets/images/sencha-avatar-64x64.png"/>' * } * }, * columns: [ * { text: 'First Name', dataIndex: 'fname', flex: 1 }, * { text: 'Last Name', dataIndex: 'lname', flex: 1 }, * { text: 'Talent', dataIndex: 'talent', flex: 1 }, * { text: 'Powers?', dataIndex: 'powers', flex: 1 } * ], * height: 400, * layout: 'fit', * fullscreen: true * }); * ``` * ```html * @example({framework: 'ext-web-components', packages:['ext-web-components'], tab: 1 }) * <ext-container width="100%" height="100%"> * <ext-grid * shadow="true" * height="275" * plugins='["rowexpander"]' * onready="rowExpanderGrid.onGridReady" * fullscreen="true" * variableHeights="true" * > * <ext-column text="First Name" dataIndex="fname" flex="1"></ext-column> * <ext-column text="Last Name" dataIndex="lname" flex="1"></ext-column> * <ext-column text="Talent" dataIndex="talent" flex="1"></ext-column> * </ext-grid> * </ext-container> * ``` * ```javascript * @example({framework: 'ext-web-components', tab: 2, packages: ['ext-web-components']}) * import '@sencha/ext-web-components/dist/ext-container.component'; * import '@sencha/ext-web-components/dist/ext-grid.component'; * import '@sencha/ext-web-components/dist/ext-column.component'; * * Ext.require('Ext.grid.plugin.RowExpander'); * * export default class RowExpanderGridComponent { * constructor() { * this.store = new Ext.data.Store({ * sorters: [ * { property: 'lname' } * ], * data: [ * { 'fname': 'Barry', 'lname': 'Allen', 'talent': 'Speedster'}, * { 'fname': 'Oliver', 'lname': 'Queen', 'talent': 'Archery'}, * { 'fname': 'Kara', 'lname': 'Zor-El', 'talent': 'All'}, * { 'fname': 'Helena', 'lname': 'Bertinelli', 'talent': 'Weapons Expert'}, * { 'fname': 'Hal', 'lname': 'Jordan', 'talent': 'Willpower' } * ] * }); * } * * onGridReady(event) { * this.rowExpanderGridCmp = event.detail.cmp; * this.rowExpanderGridCmp.setItemConfig({ body: * { * tpl: ` * <div> * <img height="100" src="http://www.sencha.com/assets/images/sencha-avatar-64x64.png"/> * <div style="font-size: 16px; margin-bottom: 5px">{fname} {lname}</div> * <div style="font-weight: bold; font-size: 14px">{title}</div> * <div style="font-weight: bold">{department}</div> * </div>` * } * }); * this.rowExpanderGridCmp.setStore(this.store); * } * } * window.rowExpanderGrid = new RowExpanderGridComponent(); * ``` * ```javascript * @example({framework: 'ext-react', packages:['ext-react']}) * import React, { Component } from 'react' * import { ExtGrid, ExtColumn } from '@sencha/ext-react'; * * Ext.require('Ext.grid.plugin.RowExpander'); * * export default class MyExample extends Component { * * store = Ext.create('Ext.data.Store', { * data: [ * { * 'fname': 'Barry', * 'lname': 'Allen', * 'title': 'Director of Engineering', * 'department': 'Engineering' * }, * { * 'fname': 'Oliver', * 'lname': 'Queen', * 'title': 'Senior Developer', * 'department': 'Engineering' * }, * { * 'fname': 'Kara', * 'lname': 'Zor-El', * 'title': 'Senior Marketing Manager', * 'department': 'Marketing' * }, * { * 'fname': 'Helena', * 'lname': 'Bertinelli', * 'title': 'Marketing Associate', * 'department': 'Marketing' * }, * { * 'fname': 'Hal', * 'lname': 'Jordan', * 'title': 'Product Manager', * 'department': 'Marketing' * } * ], * sorters: [ * { property: 'lname' } * ] * }); * * render() { * return ( * <ExtGrid * store={this.store} * fullscreen * plugins={['rowexpander']} * itemConfig={{ * body: { * tpl: (record) => ( * <div> * <img height="100" src="http://www.sencha.com/assets/images/sencha-avatar-64x64.png"/> * <div style={styles.name}>{record.fname} {record.lname}</div> * <div style={styles.title}>{record.title}</div> * <div style={styles.department}>{record.department}</div> * </div> * ) * } * }} * variableHeights * > * <ExtColumn * text="First Name" * dataIndex="fname" * flex={1} * /> * <ExtColumn * text="Last Name" * dataIndex="lname" * flex={1} * /> * <ExtColumn * text="Department" * dataIndex="department" * flex={1} * /> * </ExtGrid> * ) * } * } * * const styles = { * name: { * fontSize: '16px', * marginBottom: '5px' * }, * department: { * fontWeight: 'bold' * }, * title: { * fontWeight: 'bold', * fontSize: '14px' * } * } * ``` * ```javascript * @example({framework: 'ext-angular', packages:['ext-angular']}) * import { Component } from '@angular/core' * declare var Ext: any; * * Ext.require('Ext.grid.plugin.RowExpander'); * @Component({ * selector: 'app-root-1', * styles: [` * `], * template: ` * <ExtContainer height="600" width="900"> * <ExtGrid * [store]="store" * [fullscreen]="true" * (ready)="gridReady($event)" * [itemConfig]="configObj" * [variableHeights]="true" * > * <ExtColumn * text="First Name" * dataIndex="fname" * flex= "1" * ></ExtColumn> * <ExtColumn * text="Last Name" * dataIndex="lname" * flex= "1" * ></ExtColumn> * <ExtColumn * text="Department" * dataIndex="department" * flex= "1" * ></ExtColumn> * </ExtGrid> * </ExtContainer> * ` * }) * export class AppComponent { * configObj = { * body: { * tpl: ` * <div> * <img height="100" src="http://www.sencha.com/assets/images/sencha-avatar-64x64.png"></img> * <div style="font-size: 16px; margin-bottom: 5px">{fname} {lname}</div> * <div style="font-weight: bold">{title}</div> * <div style="font-weight: bold; font-size: 14px">{department}</div> * </div> * ` * } * }; * * store = Ext.create('Ext.data.Store', { * data: [ * { * 'fname': 'Barry', * 'lname': 'Allen', * 'title': 'Director of Engineering', * 'department': 'Engineering' * }, * { * 'fname': 'Oliver', * 'lname': 'Queen', * 'title': 'Senior Developer', * 'department': 'Engineering' * }, * { * 'fname': 'Kara', * 'lname': 'Zor-El', * 'title': 'Senior Marketing Manager', * 'department': 'Marketing' * }, * { * 'fname': 'Helena', * 'lname': 'Bertinelli', * 'title': 'Marketing Associate', * 'department': 'Marketing' * }, * { * 'fname': 'Hal', * 'lname': 'Jordan', * 'title': 'Product Manager', * 'department': 'Marketing' * } * ], * sorters: [ * { property: 'lname' } * ] * }); * * gridReady = (ele) => { * ele.ext.setPlugins({rowexpander: true}); * } * } * ``` * * @since 6.2.0 */Ext.define('Ext.grid.plugin.RowExpander', { extend: 'Ext.plugin.Abstract', requires: [ 'Ext.grid.cell.Expander' ], alias: 'plugin.rowexpander', config: { grid: null, column: { weight: -1100, xtype: 'gridcolumn', align: 'center', text: '', width: 50, resizable: false, hideable: false, sortable: false, editable: false, ignore: true, ignoreExport: true, cell: { xtype: 'expandercell' }, menuDisabled: true } }, expanderSelector: '.' + Ext.baseCSSPrefix + 'expandercell .' + Ext.baseCSSPrefix + 'icon-el', init: function(grid) { grid.setVariableHeights(true); this.setGrid(grid); }, destroy: function() { var grid = this.getGrid(), col = this.colInstance; if (col && !grid.destroying) { grid.unregisterColumn(col, true); } this.callParent(); }, applyColumn: function(column, oldColumn) { return Ext.factory(Ext.apply({}, column), null, oldColumn); }, updateGrid: function(grid) { var me = this; if (grid) { grid.hasRowExpander = true; grid.addCls(Ext.baseCSSPrefix + 'has-rowexpander'); me.colInstance = grid.registerColumn(me.getColumn()); grid.refreshScrollerSize(); grid.element.on({ tap: 'onGridTap', delegate: me.expanderSelector, scope: me }); } }, onGridTap: function(e) { var cell = Ext.Component.from(e), row = cell.row; // May have tapped on a descendant grid row. We're only interested in our own. if (row.getGrid() === this.getGrid()) { row.toggleCollapsed(); } }});