ExtJS 可重用视图和控制器
ExtJS reusable views and controllers
我刚开始使用 Extjs,我几乎没有基础 doubts.I 创建了一个简单的视图 (ScreenPropertiesPage),其中有 1 个 select 框和 1 个自定义视图。在更改 select 框值时,视图字段会更新,这是在控制器中完成的。我完成了创建视图和控制器,它具有 onchange select 框值的侦听器并更新关联的视图字段。
但现在的问题是:在我的应用程序中,我必须创建 4 个 ScreenPropertiesPage 视图实例,并且当从任何视图触发 onchange 事件时,始终更新第一个视图的文本框。如何将事件结合到特定视图?结合控制器和视图并重用它的最佳过程是什么(即使 link 到我可以学习控制器视图重用性的文档就足够了)?非常感谢任何帮助。
视图的代码框架:
Ext.define('Configurator.view.screenproperties.ScreenPropertiesPage', {
extend: 'Ext.container.Container',
alias: 'widget.screenpropertiespage',
requires: [
'Configurator.store.screenproperties.ScreenProperties'
],
autoScroll: true,
config: {
overLayMode: false
},
initComponent: function () {
var me = this;
this.items = [{
xtype: 'container',
componentCls: 'screenComboSelectorPanel',
layout: {
type: 'hbox',
align: 'center',
pack: 'center'
},
items: [{
xtype: 'combo',
store: Ext.create(
'Configurator.store.screenproperties.ScreenProperties'
),
itemId: 'screenSelector',
margin: 3,
width: 400,
listConfig: {
maxHeight: 200
},
fieldLabel: 'Screen Name',
disabledCls: 'disabledBtn',
disabled: me.getOverLayMode(),
queryMode: 'local',
emptyText: '-SELECT-',
valueField: 'screenName',
displayField: 'screenName',
forceSelection: true,
selectOnTab: true,
autoSelect: true,
height: 25,
tpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<div class="x-boundlist-item comboContainer "><div class="rowExpanedrTextArea " style="">{screenName} </div>{[this.isExpandable(xkey,parent,values,xindex)]}</div>',
'</tpl>'
),
displayTpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'{screenName}',
'</tpl>'
)
}]
}, {
xtype: 'screenpropertieseditor',
itemId: 'messagesEditor',
margin: '25',
header: true,
frame: false,
border: true,
collectionName: 'messages',
title: 'Messages'
}]
me.callParent(arguments);
}
});
当用户更改组合框中的值时,我想更新 screenpropertieseditor 类型视图。
视图控制器:
Ext.define('Configurator.controller.ScreenProperties', {
extend: 'Ext.app.Controller',
refs: [{
ref: 'screenPropertiesPage',
selector: 'screenpropertiespage'
}, {
ref: 'screenSelector',
selector: 'screenpropertiespage combobox[itemId=screenSelector]'
}, {
ref: 'screenPropertiesMessagesEditor',
selector: 'screenpropertieseditor[itemId=messagesEditor]'
}, {
ref: 'screenPropertiesPage',
selector: 'screenpropertiespage'
}],
init: function (application) {
var me = this;
this.control({
'screenpropertiespage combobox[itemId=screenSelector]': {
change: this.screenPropertiesPageStoreHandler
}
});
},
screenPropertiesPageStoreHandler: function (thisObj, eOpts) {
var messagesEditor = this.getScreenPropertiesMessagesEditor();
var screenSelector = this.getScreenSelector();
var screenSelected = screenSelector.getValue();
//Screen tile store first time loading handling
if (screenSelected === undefined) {
screenSelected = screenSelector.getStore().getAt(0).data.screenName;
}
var selectedRecord = screenSelector.getStore().findRecord(
'screenName',
screenSelected, 0, false, false, true);
if (selectedRecord != undefined) {
Ext.apply(messagesEditor, {
'screenName': screenSelected
});
try {
messagesEditor.bindStore(selectedRecord.messages());
} catch (e) {}
}
}
});
ScreenPropertiesPage 将有更多的额外字段。我必须创建 ScreenPropertiesPage 的多个实例。只要任何 ScreenPropertiesPage 视图的组合框中的值发生变化,就会触发 Configurator.controller.ScreenProperties 的 screenPropertiesPageStoreHandler 方法。但是由于我的 ref 和 selector 在控制器中不正确,它总是引用第一个 ScreenPropertiesPage 视图。
你要知道Extjs中的Controller
是singleton
.
但是您可以强制 Controller
在您的情况下 ScreenProperties
处理多个视图实例。这是通过将特定视图实例的事件触发到 Controller
来处理更复杂的逻辑来完成的。
在我举一个例子之前,你需要知道使用 refs
处理同一视图的多个实例是错误的,因为它使用了这段代码(它只是一个包装器):Ext.ComponentQuery.query('yourComponent')[0];
因此,从您的视图实例池来看,它排在第一位。
因此,您需要在控制器中摆脱 refs
,因为它不适用于同一视图的多个实例。
好吧,让我们实现这一点,并实施处理相同 view/components 的多个实例的好方法。
在您看来:
initComponent: function () {
var me = this;
this.items = [{
xtype: 'container',
componentCls: 'screenComboSelectorPanel',
layout: {
type: 'hbox',
align: 'center',
pack: 'center'
},
items: [{
xtype: 'combo',
store: Ext.create(
'Configurator.store.screenproperties.ScreenProperties'
),
itemId: 'screenSelector',
margin: 3,
width: 400,
listConfig: {
maxHeight: 200
},
fieldLabel: 'Screen Name',
disabledCls: 'disabledBtn',
disabled: me.getOverLayMode(),
queryMode: 'local',
emptyText: '-SELECT-',
valueField: 'screenName',
displayField: 'screenName',
forceSelection: true,
selectOnTab: true,
autoSelect: true,
height: 25,
tpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<div class="x-boundlist-item comboContainer "><div class="rowExpanedrTextArea " style="">{screenName} </div>{[this.isExpandable(xkey,parent,values,xindex)]}</div>',
'</tpl>'
),
displayTpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'{screenName}',
'</tpl>'
),
listeners: {
change: function (cmp, newValue, oldValue) {
this.fireEvent('onCustomChange',cmp,newValue, oldValue)
},
scope: this
}
}]
}
在您的 Controller
- ScreenProperties
中,您需要侦听此事件并处理 视图中组件的特定实例 :
init: function (application) {
var me = this;
this.listen({
// We are using Controller event domain here
controller: {
// This selector matches any originating Controller
'*': {
onCustomChange: 'onCustonChangeHandler'
}
}
});
},
onCustonChangeHandler: function(componentInstance, newValue, oldValue) {
//Your complex logic here.
//componentInstance is the instance of actual component in particular view
}
通过这种方式,您可以使用一个控制器处理同一视图的多个实例,因为在您的视图中创建的每个特定组件都是通过事件传递的。
我刚开始使用 Extjs,我几乎没有基础 doubts.I 创建了一个简单的视图 (ScreenPropertiesPage),其中有 1 个 select 框和 1 个自定义视图。在更改 select 框值时,视图字段会更新,这是在控制器中完成的。我完成了创建视图和控制器,它具有 onchange select 框值的侦听器并更新关联的视图字段。
但现在的问题是:在我的应用程序中,我必须创建 4 个 ScreenPropertiesPage 视图实例,并且当从任何视图触发 onchange 事件时,始终更新第一个视图的文本框。如何将事件结合到特定视图?结合控制器和视图并重用它的最佳过程是什么(即使 link 到我可以学习控制器视图重用性的文档就足够了)?非常感谢任何帮助。
视图的代码框架:
Ext.define('Configurator.view.screenproperties.ScreenPropertiesPage', {
extend: 'Ext.container.Container',
alias: 'widget.screenpropertiespage',
requires: [
'Configurator.store.screenproperties.ScreenProperties'
],
autoScroll: true,
config: {
overLayMode: false
},
initComponent: function () {
var me = this;
this.items = [{
xtype: 'container',
componentCls: 'screenComboSelectorPanel',
layout: {
type: 'hbox',
align: 'center',
pack: 'center'
},
items: [{
xtype: 'combo',
store: Ext.create(
'Configurator.store.screenproperties.ScreenProperties'
),
itemId: 'screenSelector',
margin: 3,
width: 400,
listConfig: {
maxHeight: 200
},
fieldLabel: 'Screen Name',
disabledCls: 'disabledBtn',
disabled: me.getOverLayMode(),
queryMode: 'local',
emptyText: '-SELECT-',
valueField: 'screenName',
displayField: 'screenName',
forceSelection: true,
selectOnTab: true,
autoSelect: true,
height: 25,
tpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<div class="x-boundlist-item comboContainer "><div class="rowExpanedrTextArea " style="">{screenName} </div>{[this.isExpandable(xkey,parent,values,xindex)]}</div>',
'</tpl>'
),
displayTpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'{screenName}',
'</tpl>'
)
}]
}, {
xtype: 'screenpropertieseditor',
itemId: 'messagesEditor',
margin: '25',
header: true,
frame: false,
border: true,
collectionName: 'messages',
title: 'Messages'
}]
me.callParent(arguments);
}
});
当用户更改组合框中的值时,我想更新 screenpropertieseditor 类型视图。
视图控制器:
Ext.define('Configurator.controller.ScreenProperties', {
extend: 'Ext.app.Controller',
refs: [{
ref: 'screenPropertiesPage',
selector: 'screenpropertiespage'
}, {
ref: 'screenSelector',
selector: 'screenpropertiespage combobox[itemId=screenSelector]'
}, {
ref: 'screenPropertiesMessagesEditor',
selector: 'screenpropertieseditor[itemId=messagesEditor]'
}, {
ref: 'screenPropertiesPage',
selector: 'screenpropertiespage'
}],
init: function (application) {
var me = this;
this.control({
'screenpropertiespage combobox[itemId=screenSelector]': {
change: this.screenPropertiesPageStoreHandler
}
});
},
screenPropertiesPageStoreHandler: function (thisObj, eOpts) {
var messagesEditor = this.getScreenPropertiesMessagesEditor();
var screenSelector = this.getScreenSelector();
var screenSelected = screenSelector.getValue();
//Screen tile store first time loading handling
if (screenSelected === undefined) {
screenSelected = screenSelector.getStore().getAt(0).data.screenName;
}
var selectedRecord = screenSelector.getStore().findRecord(
'screenName',
screenSelected, 0, false, false, true);
if (selectedRecord != undefined) {
Ext.apply(messagesEditor, {
'screenName': screenSelected
});
try {
messagesEditor.bindStore(selectedRecord.messages());
} catch (e) {}
}
}
});
ScreenPropertiesPage 将有更多的额外字段。我必须创建 ScreenPropertiesPage 的多个实例。只要任何 ScreenPropertiesPage 视图的组合框中的值发生变化,就会触发 Configurator.controller.ScreenProperties 的 screenPropertiesPageStoreHandler 方法。但是由于我的 ref 和 selector 在控制器中不正确,它总是引用第一个 ScreenPropertiesPage 视图。
你要知道Extjs中的Controller
是singleton
.
但是您可以强制 Controller
在您的情况下 ScreenProperties
处理多个视图实例。这是通过将特定视图实例的事件触发到 Controller
来处理更复杂的逻辑来完成的。
在我举一个例子之前,你需要知道使用 refs
处理同一视图的多个实例是错误的,因为它使用了这段代码(它只是一个包装器):Ext.ComponentQuery.query('yourComponent')[0];
因此,从您的视图实例池来看,它排在第一位。
因此,您需要在控制器中摆脱 refs
,因为它不适用于同一视图的多个实例。
好吧,让我们实现这一点,并实施处理相同 view/components 的多个实例的好方法。
在您看来:
initComponent: function () {
var me = this;
this.items = [{
xtype: 'container',
componentCls: 'screenComboSelectorPanel',
layout: {
type: 'hbox',
align: 'center',
pack: 'center'
},
items: [{
xtype: 'combo',
store: Ext.create(
'Configurator.store.screenproperties.ScreenProperties'
),
itemId: 'screenSelector',
margin: 3,
width: 400,
listConfig: {
maxHeight: 200
},
fieldLabel: 'Screen Name',
disabledCls: 'disabledBtn',
disabled: me.getOverLayMode(),
queryMode: 'local',
emptyText: '-SELECT-',
valueField: 'screenName',
displayField: 'screenName',
forceSelection: true,
selectOnTab: true,
autoSelect: true,
height: 25,
tpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<div class="x-boundlist-item comboContainer "><div class="rowExpanedrTextArea " style="">{screenName} </div>{[this.isExpandable(xkey,parent,values,xindex)]}</div>',
'</tpl>'
),
displayTpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'{screenName}',
'</tpl>'
),
listeners: {
change: function (cmp, newValue, oldValue) {
this.fireEvent('onCustomChange',cmp,newValue, oldValue)
},
scope: this
}
}]
}
在您的 Controller
- ScreenProperties
中,您需要侦听此事件并处理 视图中组件的特定实例 :
init: function (application) {
var me = this;
this.listen({
// We are using Controller event domain here
controller: {
// This selector matches any originating Controller
'*': {
onCustomChange: 'onCustonChangeHandler'
}
}
});
},
onCustonChangeHandler: function(componentInstance, newValue, oldValue) {
//Your complex logic here.
//componentInstance is the instance of actual component in particular view
}
通过这种方式,您可以使用一个控制器处理同一视图的多个实例,因为在您的视图中创建的每个特定组件都是通过事件传递的。