将ExtJS MVC控制器附加到DOM元素,而不是组件

时间:2011-05-18 16:20:50

标签: extjs extjs4 extjs-mvc

有没有办法使用Ext.app.Controller control()方法,但传入DOM查询?我有一个包含标准链接的页面,并希望为它们添加一个单击处理程序,即使它们不是作为Ext Buttons创建的。

我试过

Ext.define('app.controller.TabController', {
    extend: 'Ext.app.Controller',

    init: function() {
        console.log("init");
        this.control({
            'a': {
                click: this.changeTab
            }   
        });
    },

    changeTab: function() {
        alert("new tab!");
    }   
});

但点击链接不会触发警报。

有没有办法用this.control指定CSS选择器?或者它只适用于组件?

4 个答案:

答案 0 :(得分:3)

我找到了解决这个问题的方法。它并不像人们希望的那样直接,但它会将所有“动作”代码留在控制器中。

要求:将网页的html部分包含在实际的Ext.Component中。无论哪种方式都可能出现这种情况。例如,您可能有一个包含HTML的简单视图,如下所示:

Ext.define('app.view.myView', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.myView',
    title: 'My Cool Panel',
    html: '<div><a href="#">This link will open a window</a></div><br /> <label for="myInput">Type here: </label><input name="myInput" type="text" value="" />',
    initComponent: function(){
        var me = this;
        me.callParent(arguments);
    }
});

然后在控制器中使用afterrender事件将侦听器应用于DOM元素。在下面的示例中,我将说明链接(元素)和输入元素:

Ext.define('app.controller.myController', {
extend: 'Ext.app.Controller',

    init: function() {
        this.control({
            'myView': {
               afterrender: function(cmp){
                    var me = this; //the controller
                    var inputs = cmp.getEl().select('input'); // will grab all DOM inputs
                    inputs.on('keyup', function(evt, el, o){
                        me.testFunction(el); //you can call a function here
                    });

                    var links = cmp.getEl().select('a'); //will grab all DOM a elements (links)
                    links.on('click', function(evt, el, o){ 
                        //or you can write your code inline here
                        Ext.Msg.show({
                            title: 'OMG!',
                            msg: 'The controller handled the "a" element! OMG!'
                        });
                    });
                }
            }   
        });
    },
    testFunction: function(el) {
        var str = 'You typed ' + el.value;
        Ext.Msg.show({
            title: 'WOW!',
            msg: str
        });
    }   
});

你有它,DOM元素在控制器内处理并坚持MVC架构!

答案 1 :(得分:1)

不,这似乎不可能。 Ext.EventBus侦听ExtJS组件触发的事件。您的标准DOM元素不会触发这些事件。另外,使用ExtJS组件检查查询(String selector)方法,这些方法不能被DOM元素调用。如果我错了,有人可能会纠正我,但不幸的是,我很确定这是不可能的。

答案 2 :(得分:0)

我也有一个可以解决这个问题的解决方案。我使用这种技术,不过因为它有其他好处:我创建了一个应用程序范围的消息传递总线。它是我的应用程序中的一个对象,它扩展了Observable,并定义了一些事件。然后,我可以在我的应用程序中触发任何事件,包括html链接。任何想要监听这些事件的组件都可以转发它们,并且它们会像从该组件触发一样触发。

Ext.define('Lib.MessageBus', {
    extend: 'Ext.util.Observable',

    constructor: function() {
        this.addEvents( 
                  "event1",
                  "event2"
                 );
        this.callParent(arguments);
    }
});

然后,每个其他组件可以在初始化后添加:

this.relayEvents('Lib.MessageBus', ['event1','event2']);

然后听那些事件。 您可以通过执行以下操作来触发事件:

Lib.MessageBus.fireEvent('event1', 'param a', 'param b')

你可以从包括html链接在内的任何事情中做到这一点。

将应用程序的某个部分的事件发送到另一部分非常方便。

答案 3 :(得分:0)

我最近遇到了同样的问题(将mvc与一些非组件混合)。 只是想我会把它作为一个答案,因为它似乎很简单,对我有用:)

Ext.define('app.controller.TabController', {
    extend: 'Ext.app.Controller',

    init: function() {
        console.log("init");
        this.control({
           /* 'a': {
                click: this.changeTab
            } */  
        });

    var link = Ext.dom.Query.selectNode('a');

    Ext.get(link).on('click', this.changeTab);

    },

    changeTab: function() {
        alert("new tab!");
    }   
});