使用Rally过滤插件时Grid Column Renderer刷新后不触发问题咨询
This is actually not a bug—it's a side effect of how Rally's gridboard handles state persistence. Let me break down why this happens and how to fix it:
Why the Renderer Stops Working After Refresh
You've enabled stateful: true for both the field picker and inline filter controls. When you refresh the page or navigate back, Rally tries to restore the grid's state from saved state data. The catch is that saved state only stores serializable column properties (like dataIndex, text, or width)—it can't save and restore JavaScript functions like your custom renderer. So when the state is restored, your renderer gets dropped, and the column reverts to its default rendering behavior.
How to Force the Renderer to Trigger Every Time
The solution is to re-apply your custom renderer after the grid finishes loading or restoring its state. Here's a reliable way to implement this:
Modified Code with Renderer Re-application
Ext.define('CustomApp', { extend: 'Rally.app.App', componentCls: 'app', launch: function () { Ext.create('Rally.data.wsapi.TreeStoreBuilder').build({ models: ['PortfolioItem/Initiative'], enableHierarchy: true }).then({ success: this._onStoreBuilt, scope: this }); }, _onStoreBuilt: function (store) { var modelNames = ['PortfolioItem/Initiative']; var context = this.getContext(); this.add({ xtype: 'rallygridboard', context: context, modelNames: modelNames, toggleState: 'grid', plugins: [ 'rallygridboardaddnew', { ptype: 'rallygridboardfieldpicker', headerPosition: 'left', modelNames: modelNames, stateful: true, stateId: context.getScopedStateId('grid-fields') }, { ptype: 'rallygridboardinlinefiltercontrol', inlineFilterButtonConfig: { stateful: true, stateId: context.getScopedStateId('grid-filters'), modelNames: modelNames, inlineFilterPanelConfig: { quickFilterPanelConfig: { defaultFields: [ 'ArtifactSearch', 'State' ] } } } } ], gridConfig: { store: store, columnCfgs: [ 'Name', 'State', { text: 'Refined', dataIndex: 'RefinedEstimate', renderer: function (value) { console.log("RefinedEstimate:renderer"); return value + " EUR"; } } ], listeners: { // Re-apply renderer when grid finishes initial rendering viewready: function(grid) { this._reapplyRefinedRenderer(grid); }, // Re-apply renderer after state is restored on refresh/navigation staterestore: function(grid) { this._reapplyRefinedRenderer(grid); }, scope: this } }, height: this.getHeight() }); }, // Helper to reattach the custom renderer _reapplyRefinedRenderer: function(grid) { const refinedColumn = grid.columns.find(col => col.dataIndex === 'RefinedEstimate'); if (refinedColumn) { refinedColumn.renderer = function(value) { console.log("RefinedEstimate:renderer"); return value + " EUR"; }; // Refresh the view to make the renderer take immediate effect grid.getView().refresh(); } } });
How This Works
- We add listeners to the grid's
viewready(triggers on initial load) andstaterestore(triggers when state is restored after refresh/navigation) events. - The helper function
_reapplyRefinedRendererfinds the target column, reassigns the custom renderer, and refreshes the grid view to ensure the changes show up right away.
This approach keeps your stateful filtering and column selection intact while ensuring your renderer works consistently across all page loads.
内容的提问来源于stack exchange,提问作者Michael Østerberg Jakobsen

