我已经对范围问题进行了一些搜索,发现了一些问题,但我不确定它们是否符合我的情况。我真的很困惑,所以我想我也可以直接问论坛。
我有一个树形图。在该树面板中,我有一个xtype的dockedItem:' textfield'。该textfield接受一个值,并通过在特殊键事件的处理程序内的Ext.Ajax.Request将其用作ajax请求中的参数。服务器在其响应上返回一个JSON对象,该对象将被解码并包含树节点的文件夹ID。在ajax请求的SUCCESS配置中,有一个我想要运行的函数,它必须通过getNodeById(IdFromAjaxResponse)引用树的节点并展开它们。问题是我不知道如何引用这些节点。我试过这个.getStore()。getNodeById但事实证明这个'这个'指的是窗口(我猜我的容器是树面板???)。我如何参考树面板或树存储?我不想使用像getCmp等直接推荐。
一些代码可以提供帮助:
Ext.define('treePanel', {
extend: 'Ext.tree.Panel',
alias: 'widget.folderTreePanel',
//title: 'Folder Tree',
displayField: 'name',
rootVisible: false,
store: 'treeStore'
dockedItems: {
xtype: 'textfield',
name: 'Search',
allowBlank: true,
enableKeys: true,
listeners: {
specialkey: function (txtField, e) { //This handler will essentially take the search value and return the path from the DB
if (e.getKey() == e.ENTER){
var searchValue = txtField.getValue();
Ext.Ajax.request({
url: 'MyServlet',
params: {
caseType: 'search',
value: searchValue
},
success: function(response) {
response = Ext.decode(response.responseText);
var node, i=0;
expandFn = function () {
This is where I have a problem->node = this.up('treePanel').getStore().getNodeById(response.IDs[i].folderId);
node.expand();
i++;
if (i >= response.IDs.length-1) return;
expandFn();
}
}
});
}
}, scope: this
}
},
columns: [{
xtype: 'treecolumn',
text: 'Folder Name',
flex: 2,
sortable: true,
dataIndex: 'name'
},{
text: 'Folder ID',
dataIndex: 'id',
flex: 2,
sortable: true
}]
});
编辑:我找到了答案。每个事件都将触发它的实例作为参数传递给处理函数。在这种情况下,txtField
指的是文本字段本身。然后我可以遍历继承并找到面板。
然而现在有一个新问题。 expandFn()
被称为ONCE然后停止,因为'节点'未定义。它应该递归,直到响应数组中没有更多项。我再次认为这是一个范围问题,但我真的很困惑,我似乎没有看到出错...
答案 0 :(得分:2)
listeners
配置有一个属性scope
。您可以将其设置为树面板。
[编辑]在特殊键侦听器中,将this
分配给变量。在success
回调中,范围与特殊键的侦听器中的范围不同。请参阅下面的修改后的代码。
listeners: {
scope: this,
specialkey: function (txtField, e) {
var me = this;
if (e.getKey() == e.ENTER){
var searchValue = txtField.getValue();
Ext.Ajax.request({
url: 'MyServlet',
params: {
caseType: 'search',
value: searchValue
},
success: function(response) {
response = Ext.decode(response.responseText);
var node, i=0;
expandFn = function () {
node = me.getStore().getNodeById(response.IDs[i].folderId);
node.expand();
i++;
if (i >= response.IDs.length-1) return;
expandFn();
}
}
});
}
}
答案 1 :(得分:0)
问题是,您的范围this
是指定义树面板时的当前范围。当即将定义此树面板时,您无法将范围设置为树面板的实例。
要解决此问题,您可以在树面板中添加initComponent
函数并在其中设置dockedItems配置:
Ext.define('treePanel', {
extend: 'Ext.tree.Panel',
// [...]
initComponent: function() {
this.dockedItems = {
// [...]
};
this.callParent();
}
});
不同之处在于initComponent
是树面板的成员函数,在组件实例化期间由框架自动调用。目前,您已经有一个实例this
,您可以将其用作文本字段听众的scope
。
答案 2 :(得分:0)
它已经超过一年了,现在对extjs和javascript基础知识更加熟练。以下是回答这个问题时应该知道的一些事情:
success callback
- >在javascript中始终引用调用我们使用它的函数的对象。在我的情况下,由于函数是ajax请求的treepanel
,因此无法引用var treepanel = txtField.up('treePanel');
。要解决此类问题,最好在函数顶部设置对您希望能够访问的对象的引用。在我的情况下,我可以expandFn
来获取对该面板的引用。
expandFn
- >首先,closure
在成功回调中定义,这是另一个函数。这会创建一个expandFn
,我们不希望这样。如果我们不准备处理它,闭包提供了一些可能导致问题的特殊功能。取treePanel
并在node = this.up('treePanel')...
的范围内定义它。这里最基本的问题是this
txtField
关键字再次没有引用我认为它的treePanel
。这就是我们之前定义node.expand()
的原因。我们可以通过它访问商店。另外node.on('expand', Ext.bind(treePanel.expandFn, treePanel, [args]), treePanel, {single:true})
需要时间来完成,特别是如果节点未加载并且我们必须发出服务器请求。对于这种情况,正确的递归方法是添加一个监听器:
Ext.bind
有些事情需要注意:
expandFn
而不是默认传递给expand
事件的参数,我们必须使用node.on('expand', treePanel.expandFn, treePanel, {single:true})
。如果我们写了expand
那么当expandFn
事件被触发时它将触发eOpts
但是它的默认参数根据文档是扩展节点本身和{single: true}
事件选项对象。expandFn
以确保仅在下一个'expand'
事件中触发node.expand()
。我们不希望每次扩展节点时都触发它。onclick
。这个答案不能完全应用于上面提供的代码,但它解释了它的问题以及应该怎样做才能解决它。