使子元素听取extJS事件

时间:2012-06-22 13:10:43

标签: javascript extjs

我是extJS的新手,也许我只是不知道正确的策略,所以如果你愿意,你可以告诉我一个更好的解决方案。

我在尝试什么: 我有一个extJS网格。在双击时,应显示ExtJS Window容器(用于详细设置),其中包含多个选项卡。该窗口具有设置被点击元素的ID的功能。窗口中的每个选项卡也需要此ID。因此,当在窗口容器中更改ID时,我希望通过有关已更改ID的事件通知每个选项卡容器。

我的问题是,我无法从选项卡访问窗口以添加侦听器,因为窗口在第一次打开之前不会呈现。

如果您查看我的源代码,也许您可​​以更好地理解我的问题:

窗口 (双击网格元素时调用setCustomerId()和show())

Ext.define('myApp.path.view.Edit', {
extend: 'Ext.window.Window',
alias: 'widget.myEdit',

title: 'Edit',
height: 500,
width: 1000,
layout: 'fit',
closeAction: 'hide',

/**
 * Initialize my custom event
 */
initComponent: function() {
    this.addEvents('customerChanged');

    this.callParent();
},

/**
 * Sets the current customerId and fires a customerChanged event
 * @param {Number} customerId
 */
setCustomerId: function(customerId) {
    this.customerId = customerId;
    this.fireEvent('customerChanged', this.customerId);
},

/**
 * create a container for the editor tabs
 */
items: [{
    xtype: 'tabpanel',
    items: [
        {
            xtype: 'myTab'
        }
    ]
}]
})

示例标签

Ext.define('myApp.path.view.myTab', {
extend: 'Ext.container.Container',
alias: 'widget.myTab',

title: 'Customer',
layout: 'fit',

/**
 * Listen to my custom event 
 * PROBLEM: works, but only after the window has been displayed one time
 */
afterRender: function() {
    this.findParentByType('window').addListener("customerChanged",   this.onCustomerChanged)
    this.callParent();
},

/**
 * Listen to my custom event 
 * PROBLEM: doesn't work, findParentByType('window') is undefined
 */
initComponent: function() {
    this.findParentByType('window').addListener("customerChanged",   this.onCustomerChanged)
    this.callParent();
},

onCustomerChanged: functio() {}

})

我希望你能理解我的意图。 谢谢!

1 个答案:

答案 0 :(得分:0)

不知道网格的itemdblclick事件的代码(它会有所帮助),但我看到的是:

itemdblclick: function(v, m) {
    var id = m.get('id'); 

    //think you are not created a window each time, having the "closeAction: 'hide'" in the code
    //if for simplicity sake, for sure it should not be here
    if (!this.detailsWin) {
        this.detailsWin = Ext.create('myApp.path.view.Edit'); 
    }

    //you set the ID and after it shows the window
    //that is why for the first time event listener is bot working
    this.detailsWin.setCustomerId(id);

    //showing the window
    this.detailsWin.show();    
}

如果是这样,您需要在setCustomerId之后调用show

    this.detailsWin.show(); 
    this.detailsWin.setCustomerId(id);

或简单覆盖窗口中的模板方法:

/**
 * @template
 */
onShow: function() {
    //firing the event
    //should be checking here if the ID was really changed
    this.fireEvent('customerChanged', this.customerId);

    //call parent to show the window
    this.callParent(arguments);
}

然后您可以按任意顺序运行show setCustomerId

或使用回调函数调用window的show方法:

this.detailsWin.show(null, function(){ 
    this.setCustomerId(id);
});

但请确保窗口是模态的,因为窗口不是模态的,并且显示您将单击网格的行,打开后回调函数将无法正常工作。

问题。

不过,您应该注意到使用这种机制并在窗口中有多个选项卡。 例如A,B,C,其中A为活动标签。 B和C选项卡在呈现之前不会监听customerChanged事件(没有客户ID)。因此,当第一次打开窗口时,将调用A选项卡的onCustomerChanged并且A选项卡将知道ID,但B和C选项卡对此一无所知(因为它们在您激活之前不会被渲染/打开它们并且未使用它们的onCustomerChanged事件侦听器。这就是这种方法的问题。

显示具有所有呈现的选项卡的窗口将起作用,但是对于所有呈现的选项卡进行更改不是最好的方法,尤其是在每个选项卡上加载数据等的大量组件时。用户可能需要例如只有一个10的标签可以做一些事情,对所有已经渲染的标签进行更改是很难的。

再加上dbl点击一个网格中相同的记录,将使用相同的ID打开同一个窗口2次 - 所以最好在触发事件之前检查ID是否已更改。

为了解决上述问题,我建议在每个选项卡内部的选项卡中使用activate事件,它自己的customerID属性用于跟踪它的更改,当然还有一个获取传递给窗口的当前ID的方法。为此,您可以使用在窗口内使用每个选项卡类扩展的基本选项卡类,或使用mixin为选项卡提供通用功能。 如果要保存最后一个活动选项卡(从上一个时间窗口打开),则在正在显示的窗口上处理活动(运行相同的选项卡通用代码)选项卡,因为activate事件在窗口时不会被触发每次使用tabpanel setActiveTab方法显示窗口时,都会打开或只设置活动选项卡,最好的位置是覆盖onShow模板方法。 当然,从选项卡中删除添加事件侦听器。