我有一个应用程序使用选项卡布局,该网格面板在绑定到每个选项卡的每个表单面板之间共享为 xtype 小部件。
我的主选项卡布局如下:
Ext.define('cardioCatalogQT.view.main.Main', {
extend: 'Ext.tab.Panel',
xtype: 'main-view',
controller: 'main-view',
requires: [
'cardioCatalogQT.view.main.MainController',
'cardioCatalogQT.view.main.MainModel',
'Ext.ux.form.ItemSelector',
'Ext.tip.QuickTipManager',
'Ext.layout.container.Card'
],
style: 'background-color:#dfe8f5;',
width: '100%',
height: 400,
layout: 'vbox',
defaults: {
bodyPadding: 5
},
items: [{
title:'Main',
region: 'south',
xtype: 'form',
itemId: 'Ajax',
flex: 1,
styleHtmlContent: true,
items:[{
xtype: 'image',
src: 'resources/images/R3D3.png',
height: 50,
width: 280
},{
title: 'Ad Hoc Sandbox for Cohort Discovery'
}] ,
lbar:[{
text: 'Initiate advanced request',
xtype: 'button',
handler: function(button){
var url = 'https://url_here';
//cardioCatalogQT.service.UtilityService.http_auth(button);
window.open(url);
}
}]
},
/*{
xtype: 'resultsGrid'
//disabled: true
},*/
/*{
xtype: 'searchGrid'
//disabled: true
},*/
{
xtype: 'demographicGrid'
//disabled: true
},
{
xtype: 'vitalGrid'
//disabled: true
},
{
xtype: 'labGrid'
//disabled: true
},
{
xtype: 'diagnosisGrid'
//disabled: true
},
{
xtype: 'medicationGrid'
//disabled: true
},
{
xtype: 'procedureGrid'
//disabled: true
},
{
xtype: 'queryGrid'
//disabled: true
}
]
});
共享相同网格小部件(特别是人口统计网格、重要网格、实验室网格、诊断网格、程序网格和药物网格,每个选项卡在主视图中由 xtype 引用)的各个选项卡如下所示:
/**
* Widget with template to render to Main view
*/
Ext.define('cardioCatalogQT.view.grid.DemographicGrid', {
extend: 'Ext.form.Panel',
alias: 'widget.demographicGrid',
itemId: 'demographicGrid',
store: 'Payload',
requires: [
'cardioCatalogQT.view.main.MainController'
],
config: {
variableHeights: false,
title: 'Demographics',
xtype: 'form',
width: 200,
bodyPadding: 10,
defaults: {
anchor: '100%',
labelWidth: 100
},
// inline buttons
dockedItems: [ {
xtype: 'toolbar',
height: 100,
items: [{
xtype: 'button',
text: 'Constrain sex',
itemId: 'showSex',
hidden: false,
listeners: {
click: function (button) {
button.up('grid').down('#sexValue').show();
button.up('grid').down('#hideSex').show();
button.up('grid').down('#showSex').hide();
}
}
}, {
xtype: 'button',
text: 'Hide sex constraint',
itemId: 'hideSex',
hidden: true,
listeners: {
click: function (button) {
button.up('grid').down('#sexValue').hide();
button.up('grid').down('#sexValue').setValue('');
button.up('grid').down('#hideSex').hide();
button.up('grid').down('#showSex').show();
}
}
},{ // Sex
xtype: 'combo',
itemId: 'sexValue',
queryMode: 'local',
editable: false,
value: 'eq',
triggerAction: 'all',
forceSelection: true,
fieldLabel: 'Select sex',
displayField: 'name',
valueField: 'value',
hidden: true,
store: {
fields: ['name', 'value'],
data: [
{name: 'female', value: 'f'},
{name: 'male', value: 'm'}
]
}
}, {
xtype: 'button',
text: 'Constrain age',
itemId: 'showAge',
hidden: false,
listeners: {
click: function (button) {
button.up('grid').down('#ageComparator').show();
button.up('grid').down('#ageValue').show();
button.up('grid').down('#hideAge').show();
button.up('grid').down('#showAge').hide();
}
}
}, {
xtype: 'button',
text: 'Hide age',
itemId: 'hideAge',
hidden: true,
listeners: {
click: function (button) {
button.up('grid').down('#ageComparator').hide();
button.up('grid').down('#ageValue').hide();
button.up('grid').down('#upperAgeValue').hide();
button.up('grid').down('#ageComparator').setValue('');
button.up('grid').down('#ageValue').setValue('');
button.up('grid').down('#upperAgeValue').setValue('');
button.up('grid').down('#hideAge').hide();
button.up('grid').down('#showAge').show();
}
}
}, { // Age
xtype: 'combo',
itemId: 'ageComparator',
queryMode: 'local',
editable: false,
value: '',
triggerAction: 'all',
forceSelection: true,
fieldLabel: 'Select age that is',
displayField: 'name',
valueField: 'value',
hidden: true,
store: {
fields: ['name', 'value'],
data: [
{name: '=', value: 'eq'},
{name: '<', value: 'lt'},
{name: '<=', value: 'le'},
{name: '>', value: 'gt'},
{name: '>=', value: 'ge'},
{name: 'between', value: 'bt'}
]
},
listeners: {
change: function(combo, value) {
// use component query to toggle the hidden state of upper value
if (value === 'bt') {
combo.up('grid').down('#upperAgeValue').show();
} else {
combo.up('grid').down('#upperAgeValue').hide();
}
}
}
},{
xtype: 'numberfield',
itemId: 'ageValue',
fieldLabel: 'value of',
value: '',
hidden: true
},{
xtype: 'numberfield',
itemId: 'upperAgeValue',
fieldLabel: 'and',
hidden: true
},{
xtype: 'button',
text: 'Constrain race/ethnicity',
itemId: 'showRace',
hidden: false,
listeners: {
click: function (button) {
button.up('grid').down('#raceValue').show();
button.up('grid').down('#hideRace').show();
button.up('grid').down('#showRace').hide();
}
}
}, {
xtype: 'button',
text: 'Hide race/ethnicity constraint',
itemId: 'hideRace',
hidden: true,
listeners: {
click: function (button) {
button.up('grid').down('#raceValue').hide();
button.up('grid').down('#raceValue').setValue('');
button.up('grid').down('#hideRace').hide();
button.up('grid').down('#showRace').show();
}
}
},{ // Race
xtype: 'combo',
itemId: 'raceValue',
queryMode: 'local',
editable: false,
value: 'eq',
triggerAction: 'all',
forceSelection: true,
fieldLabel: 'Select race',
displayField: 'name',
valueField: 'value',
hidden: true,
store: {
fields: ['name', 'value'],
data: [
{name: 'female', value: 'f'},
{name: 'male', value: 'm'}
]
}
},{
//minWidth: 80,
text: 'Add to search',
xtype: 'button',
itemId: 'searchClick',
handler: 'onSubmitDemographics'
}]
},
{
xtype:'searchGrid'
}
]
}
});
选项卡中每个表单面板之间的唯一区别是项目组件。这些表单面板中的每一个都引用了一个“searchGrid”的 xtype 并将其呈现在所附图像中:
问题是我有同一个网格的 6 个实例。这在大多数情况下都有效,但它会导致一些与控制我的网格中的复选框以及一些奇怪的网格存储加载行为相关的问题,老实说,使用这种反模式跟踪组件是一个 PITA。
我想以某种方式在下部垂直面板中有一个我的 searchGrid 实例,而上部垂直面板具有我需要根据每个选项卡的要求更改的项目组件。项目控件如何变化的一个示例是
我想要的行为是,当我单击选项卡时,上部项目组件会将我带到不同的表单面板,而下部面板则固定在搜索网格上。
但是,我目前将 searchGrid 绑定到每个选项卡的表单面板,因为这是我可以让它工作的唯一方法。
searchGrid 网格面板如下所示:
Ext.define('cardioCatalogQT.view.grid.Search', {
extend: 'Ext.grid.Panel',
xtype: 'framing-buttons',
store: 'Payload',
itemId: 'searchGrid',
requires: [
'cardioCatalogQT.view.main.MainController'
],
columns: [
{text: "ID", width: 50, sortable: true, dataIndex: 'id'},
{text: "Type", width: 120, sortable: true, dataIndex: 'type'},
{text: "Key", flex: 1, sortable: true, dataIndex: 'key'},
{text: "Criteria", flex: 1, sortable: true, dataIndex: 'criteria'},
{text: "DateOperator", flex: 1, sortable: true, dataIndex: 'dateComparatorSymbol'},
{text: "When", flex: 1, sortable: true, dataIndex: 'dateValue'},
{text: "Count", flex: 1, sortable: true, dataIndex: 'n'}
],
columnLines: true,
selModel: {
type: 'checkboxmodel',
listeners: {
selectionchange: 'onSelectionChange'
}
},
// When true, this view acts as the default listener scope for listeners declared within it.
// For example the selectionModel's selectionchange listener resolves to this.
defaultListenerScope: false,
// This view acts as a reference holder for all components below it which have a reference config
// For example the onSelectionChange listener accesses a button using its reference
//referenceHolder: true,
// inline buttons
dockedItems: [{
xtype: 'toolbar',
dock: 'bottom',
ui: 'footer',
layout: {
pack: 'center'
}
}, {
xtype: 'toolbar',
items: [{
//reference: 'andButton',
text: 'AND',
itemId: 'andButton',
tooltip: 'Add the selected criteria as AND',
iconCls: 'and',
disabled: true,
handler: 'onCriterionAnd'
},'-',{
//reference: 'orButton',
text: 'OR',
itemId: 'orButton',
tooltip: 'Add the selected criteria as OR',
iconCls: 'or',
disabled: true,
handler: 'onCriterionOr'
},'-',{
//reference: 'notButton',
text: 'NOT',
itemId: 'notButton',
tooltip: 'Add the selected criteria as NOT',
iconCls: 'not',
disabled: true,
handler: 'onCriterionNot'
},'-',{
//reference: 'removeButton', // The referenceHolder can access this button by this name
text: 'Remove',
itemId: 'removeButton',
tooltip: 'Remove the selected item',
iconCls: 'remove',
disabled: true,
handler: 'onCriterionRemove'
},'-', { // SaveQuery
//reference: 'SaveQuery',
text: 'Save',
itemId: 'saveQuery',
tooltip: 'save the current filter',
iconCls: 'save',
disabled: true,
handler: 'onFilterSave'
}]
}],
height: 1000,
frame: true,
iconCls: 'icon-grid',
alias: 'widget.searchGrid',
title: 'Search',
initComponent: function() {
this.width = 750;
this.callParent();
}
});
我搞砸了使用 Vbox 布局来获得我想要的行为,但相当不成功。这似乎并不少见的用例使上部 Vbox 面板基于 Tab 单击更改为不同的表单面板,而下部 Vbox 面板保持固定。任何见解都将受到欢迎。