在自定义Store中使用PortfolioItem/Feature模型遇格式问题求助
我正在做一个特性(非用户故事)及其依赖关系的概览功能,流程是:
- 拉取按版本过滤的WSAPI Store
- 获取前置与后置集合来展示对应值
原本想直接把这个WSAPI Store用在网格里,但执行onScopeChange(版本过滤生效)时,网格渲染会早于前置/后置集合加载完成,所以改用了custom.store绑定到网格,这部分操作是正常的。
但现在遇到个问题:我需要自己处理大部分网格格式化,已经把自定义Store的model设置为PortfolioItem/Feature,本来期望网格能自动应用该模型的格式化,但并没有生效。用WSAPI Store的时候,Release和State字段能正常格式化,换成自定义Store后这两个字段就显示异常了。
相关代码如下:
自定义Store代码
_getViewStore: function () { var me = this; /* Extract data from featureStore */ var records = me.myFeatureStore.getRecords(); /* Create new, update, store for adding into grid */ if (!me.myViewStore) { me.myViewStore = Ext.create('Rally.data.custom.Store', { model: 'PortfolioItem/Feature', data: records, }); } else { me.myViewStore.removeAll(); me.myViewStore.add(records); } }
网格代码
_createGrid: function () { var me = this; me.myGrid = Ext.create('Ext.Container', { items: [{ xtype: 'rallygrid', store: me.myViewStore, columnCfgs: [{ xtype: 'gridcolumn', align: 'left', tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate'), text: 'Predecessors', dataIndex: 'Predecessors', width: 200, renderer: function (value, metaData, record) { var mFieldOutputPre = ''; var records = record.predecessorStore.getRecords(); _.each(records, function (feature) { mFieldOutputPre += Rally.nav.DetailLink.getLink({ record: feature, text: feature.get('FormattedID'), showTooltip: true }); // Add the feature name and a line break. mFieldOutputPre += ' - ' + feature.get('Name') + '<br>'; }); return mFieldOutputPre; }, }, { text: 'FormattedID', dataIndex: 'FormattedID', xtype: 'templatecolumn', tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate') }, { text: 'Name', dataIndex: 'Name', flex: 1 }, { text: 'Release', dataIndex: 'Release', flex: 1 }, { text: 'State', dataIndex: 'State', flex: 1 }, { // Column 'Successors' xtype: 'templatecolumn', align: 'left', tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate'), text: 'Successors', dataIndex: 'Successors', width: 200, renderer: function (value, metaData, record) { var mFieldOutputSuc = ''; var records = record.successorStore.getRecords(); _.each(records, function (feature) { mFieldOutputSuc += Rally.nav.DetailLink.getLink({ record: feature, text: feature.get('FormattedID'), showTooltip: true }); // Add the feature name and a line break. mFieldOutputSuc += ' - ' + feature.get('Name') + '<br>'; }); return mFieldOutputSuc; }, }] }], renderTo: Ext.getBody() }); me.add(me.myGrid); }
想请教下:这种场景下能不能让自定义Store应用PortfolioItem/Feature模型的格式化?如果可以的话,我哪里操作错了?
首先明确:是可以让自定义Store应用模型的自动格式化的,你的问题出在自定义Store初始化和数据传递的细节上,下面给你拆解问题和修复方案:
1. 自定义Store的data参数问题
你直接把me.myFeatureStore.getRecords()拿到的记录丢给自定义Store的data属性,这里有个坑:WSAPI Store返回的是Rally数据模型实例,但Rally.data.custom.Store在接收data的时候,默认会把这些实例转成普通的JSON对象,丢失了模型关联的格式化逻辑、getter方法等。
这就是为什么Release和State字段显示异常——原来的WSAPI记录会通过模型的格式化器处理这些关联对象(比如Release会显示名称+链接,State会显示对应状态的样式),但转成普通对象后,这些信息只剩下原始的ref或者ID,自然没法正确渲染。
2. 修复方案:让自定义Store保留模型实例
你需要给自定义Store加上dataType: 'records'配置,告诉它直接接收并保留Rally模型实例,而不是转成JSON:
me.myViewStore = Ext.create('Rally.data.custom.Store', { model: 'PortfolioItem/Feature', data: records, dataType: 'records' // 关键配置,保留原始记录实例 });
加上这个配置后,自定义Store里的记录就和WSAPI Store里的一样,是完整的模型实例,网格就能自动调用模型对应的格式化器来处理Release、State这些字段了。
3. 额外注意点:前置/后置集合的加载时机
你之前遇到的网格渲染早于前置/后置集合加载的问题,在改用自定义Store后,要确保me.myFeatureStore里的所有记录的predecessorStore和successorStore都已经加载完成,再把记录添加到自定义Store里。否则网格里的前置/后置列可能还是会显示空或者不完整的数据。
可以在WSAPI Store的load事件里,等所有关联集合加载完成后再调用_getViewStore方法,比如用Ext.Deferred来批量处理:
// 假设me.myFeatureStore是你的WSAPI Store me.myFeatureStore.on('load', function(store, records) { var promises = []; _.each(records, function(record) { // 等待前置集合加载完成 var preDeferred = Ext.create('Ext.Deferred'); record.predecessorStore.load({ callback: function() { preDeferred.resolve(); } }); promises.push(preDeferred); // 等待后置集合加载完成 var sucDeferred = Ext.create('Ext.Deferred'); record.successorStore.load({ callback: function() { sucDeferred.resolve(); } }); promises.push(sucDeferred); }); // 所有关联集合都加载完后再更新自定义Store和网格 Ext.Deferred.all(promises).then(function() { me._getViewStore(); me.myGrid.down('rallygrid').reconfigure(me.myViewStore); }); });
这样就能保证网格渲染的时候,所有需要的数据都已经准备好,不管是基础字段的格式化,还是前置/后置依赖的展示,都能正常工作。
内容的提问来源于stack exchange,提问作者Michael Østerberg Jakobsen

