ExtJs技术求助:为表格元素添加Tooltip及动态循环渲染列
ExtJS表格开发问题解决方案
1. 表格单元格添加Tooltip(解决作用域问题)
方案1:利用data-qtip属性(最简实现)
ExtJS原生支持识别单元格的data-qtip属性自动生成Tooltip,无需额外处理作用域,直接在renderer中设置即可:
// 修改sell列renderer renderer: function (value, gridcell, record) { value = record.get('sell')[4 - index]; if (value) { gridcell.tdCls = 'sell'; // 自定义Tooltip内容,替换为你需要的字段 gridcell.set({ 'data-qtip': `数量:${value.quantity}\n备注:${value.remark || '无'}` }); return ('Example' || '') + '<br />' + value.quantity; } else { gridcell.tdCls = ''; gridcell.set({'data-qtip': ''}); // 清空无值单元格的Tooltip return ''; } } // buy列和price列同理,在renderer中添加对应data-qtip设置
方案2:全局绑定Tooltip(复杂场景适用)
如果需要自定义Tooltip样式或逻辑,可在Grid初始化时创建全局Tooltip,通过scope绑定Grid实例解决作用域问题:
initComponent: function() { this.callParent(arguments); Ext.create('Ext.tip.ToolTip', { target: this.getView().el, delegate: '.x-grid-cell', trackMouse: true, renderTo: Ext.getBody(), listeners: { beforeshow: function(tip) { var cell = tip.triggerElement; var record = this.getView().getRecord(cell); var colIndex = this.getView().getCellIndex(cell); let tipText = ''; // 根据列位置判断是sell/price/buy列,生成对应Tooltip内容 const sellLen = record.get('sell').length; if (colIndex < sellLen) { const sellItem = record.get('sell')[sellLen - 1 - colIndex]; tipText = sellItem ? `数量:${sellItem.quantity}` : ''; } else if (colIndex === sellLen) { const totalQty = record.get('sell').reduce((sum, item) => sum + Number(item.quantity), 0) + record.get('buy').reduce((sum, item) => sum + Number(item.quantity), 0); tipText = `总价:${Common.Formatter.to4PrecisionPrice(record.get('price'))}\n总数量:${totalQty}`; } else { const buyIndex = colIndex - sellLen - 1; const buyItem = record.get('buy')[buyIndex]; tipText = buyItem ? `数量:${buyItem.quantity}` : ''; } tip.update(tipText); return !!tipText; // 无内容时不显示Tooltip }, scope: this // 绑定Grid实例,确保能正确获取record和视图信息 } }); }
2. 动态适配sell/buy数组长度生成列
实现思路
不再固定length:5,而是根据Store中第一条记录的sell、buy数组长度动态生成列,同时监听Store加载事件确保数据更新后列同步调整:
initComponent: function() { this.callParent(arguments); // 监听Store加载事件,动态生成列 this.getStore().on('load', function(store) { if (store.isEmpty()) return; const firstRecord = store.first(); const sellLen = firstRecord.get('sell').length; const buyLen = firstRecord.get('buy').length; // 生成sell列 const sellColumns = Array.from({ length: sellLen }, (_, index) => ({ renderer: function (value, gridcell, record) { value = record.get('sell')[sellLen - 1 - index]; if (value) { gridcell.tdCls = 'sell'; gridcell.set({'data-qtip': `数量:${value.quantity}`}); return ('Example' || '') + '<br />' + value.quantity; } else { gridcell.tdCls = ''; gridcell.set({'data-qtip': ''}); return ''; } }, width: 100 // 自定义列宽 })); // 中间的price列 const priceColumn = { dataIndex: 'price', renderer: function (value, gridcell, record) { let quantity = 0; record.get('sell').forEach(num => quantity += Number(num.quantity)); record.get('buy').forEach(num => quantity += Number(num.quantity)); gridcell.tdCls = 'amount'; gridcell.set({'data-qtip': `总价:${Common.Formatter.to4PrecisionPrice(value)}\n总数量:${quantity}`}); return `${Common.Formatter.to4PrecisionPrice(value)}<br />${quantity}`; }, width: 120 }; // 生成buy列 const buyColumns = Array.from({ length: buyLen }, (_, index) => ({ renderer: function (value, gridcell, record) { value = record.get('buy')[index]; if (value) { gridcell.tdCls = 'buy'; gridcell.set({'data-qtip': `数量:${value.quantity}`}); return ('Example' || '') + '<br />' + value.quantity; } else { gridcell.tdCls = ''; gridcell.set({'data-qtip': ''}); return ''; } }, width: 100 })); // 重新配置表格列 this.reconfigure(store, [...sellColumns, priceColumn, ...buyColumns]); }, this); // 可选:监听Store数据变更事件,适配动态更新的数据 this.getStore().on('datachanged', function(store) { // 重复上述列生成逻辑,或直接触发load事件处理函数 this.getStore().fireEvent('load', store); }, this); }
注意事项
- 如果Store是预加载数据,可直接在
initComponent中获取第一条记录生成列,无需监听load事件; - 若sell/buy数组长度在不同记录中不一致,需额外处理(比如取最大长度统一生成列)。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

