/** * Use this component to render a React element inside of a grid cell. * * <Grid> * <Column text="Actions" dataIndex="name"> * <RendererCell * renderer={(value, record) => ( * <Button text={`Call ${value}`} handler={this.onCallClick.bind(this, record)}/> * )} * /> * </Column> * </Grid> * * RendererCell is automatically used when a Column contains a renderer prop. The following * is equivalent to the example above: * * <Grid> * <Column * text="Actions" * dataIndex="name" * renderer={(value, record) => ( * <Button text={`Call ${value}`} handler={this.onCallClick.bind(this, record)}/> * )} * /> * </Grid> * @since 6.5.1 */Ext.define('Ext.reactor.RendererCell', { extend: 'Ext.grid.cell.Base', xtype: 'renderercell', config: { /** * @cfg {Function} renderer * A function that returns a React element or text to render. It is passed * the following arguments: * @cfg {Object} renderer.value The data value for the current cell. * @cfg {Ext.data.Model} renderer.record The record for the current row. * @cfg {Number} renderer.dataIndex The dataIndex of the current column. * @cfg {Ext.grid.cell.Base} renderer.cell The current cell. * @cfg {Ext.grid.column.Column} renderer.column The current column. * @cfg {React.Element/String} renderer.return The React element or text to be * rendered. */ renderer: null, /** * @cfg {Function} summaryRenderer * A function that returns a React element or text to render in the summary * row. It is passed the following arguments: * @cfg {Object} renderer.value The data value for the current cell. * @cfg {React.Element/String} renderer.return The React element or text to be * rendered. */ summaryRenderer: null, /** * @cfg {Boolean} forceWidth * `true` to measure the available width of the cell and set that * width on the underlying widget. If `false`, the widget width will auto * size. */ forceWidth: false }, setValue: function (value) { var me = this, context = me.refreshContext, column = context.column, needsSizing = false, scope = column.getScope(), markup, renderer, result; if (context.summary) { renderer = me.getSummaryRenderer() || column.getSummaryRenderer(); } renderer = renderer || me.getRenderer() || column.getRenderer(); if (renderer) { markup = renderer.call(scope, value, context.record, context.dataIndex, me, column); if (typeof markup === 'object') { // Ext.reactor.ReactDOM is set by reactor before the app is launched result = Ext.reactor.ReactDOM.render(markup, me.bodyElement.dom); if (result.isWidget) { needsSizing = result !== me.widget; me.widget = result; } } else { if (markup == null) { markup = ''; } Ext.dom.Helper.overwrite(me.bodyElement, Ext.htmlEncode(markup.toString())); me.widget = null; } if (needsSizing && me.getForceWidth()) { me.setWidgetWidth(me.getWidth()); } } return me; }, updateWidth: function (width, oldWidth) { this.callParent(arguments); if (this.getForceWidth()) { this.setWidgetWidth(width); } }, doDestroy: function () { this.widget = null; Ext.reactor.ReactDOM.unmountComponentAtNode(this.bodyElement.dom); this.callParent(); }, privates: { setWidgetWidth: function (width) { var me = this, el = me.bodyElement, widget, column, leftPad, rightPad; if (!me.rendered) { return; } widget = me.widget; if (widget) { column = me.getColumn(); leftPad = parseInt(column.getCachedStyle(el, 'padding-left'), 10) || 0; rightPad = parseInt(column.getCachedStyle(el, 'padding-right'), 10) || 0; // Give the widget a reference to ourself to allow it to do extra measuring widget.measurer = column; widget.setWidth(width - leftPad - rightPad); } } }});