ExtJS 4.1 Call One Controller From Another

2020-05-27 10:31发布

Note: I'm a total ignoramus regarding javascript.

I've broken my ExtJS 4.1 MVC app out into several controllers like:

/app/controller/Auth
    |          |Quiz
    |          |Result
    |          |Blah...
    |model/...

I want to respond to an "event", not a DOM Event, rather a Ext.form.action.Submit.success event by calling functions in both my Auth and Quiz controllers. The summarized code for the first part is here:

// File: app/controller/Auth.js
attemptLogin : function() {
    var form = Ext.ComponentQuery.query('#loginpanel')[0].form;
    if (form.isValid()) {
        form.submit({
        success : function(form, action) {
            // THIS IS THE FUNCTION FROM THE CURRENT CONTROLLER
            Assessor.controller.Auth.prototype.finishLogin();
            // THIS IS THE FUNCTION FROM THE OTHER CONTROLLER
            Assessor.controller.Quiz.prototype.setupAssessment();
        },

This works but feels wrong. Is there a proper way to do this? It seems like I should fire a unique event that is listened to by both controllers, but I can't understand how to do that with Ext.Event. Any guidance?

Thanks! I'm really grateful for all the great ideas and advice.

5条回答
男人必须洒脱
2楼-- · 2020-05-27 11:08

I have also been looking for this and all you need is Asanda.app.getController('quiz').setupAssignment();, where Asanda is the name of your app

查看更多
The star\"
3楼-- · 2020-05-27 11:09

It makes sense to me to fire a custom event from the form and simply listen to it in both your controllers, like what you said here:

It seems like I should fire a unique event that is listened to by both controllers

// File: app/controller/Auth.js
attemptLogin : function() {
    var form = Ext.ComponentQuery.down('#loginpanel').form;
    if (form.isValid()) {
        form.submit({
        success : function(form, action) {
            // fire the event from the form panel
            form.owner.fireEvent('loginsuccess', form.owner);
        },

Then in each of your controllers you can listen to it with Controller#control, like this:

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

    init: function() {
        var me = this; 

        me.control({

            '#loginpanel': {

                loginsuccess: me.someHandler

            }
        });
    },

    someHandler: function(form) {
        //whatever needs to be done
        console.log(form);
    }
}

And then add the same thing to your Quiz controller:

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

    init: function() {
        var me = this; 

        me.control({

            '#loginpanel': {

                loginsuccess: me.someOtherHandler

            }
        });
    },

    someOtherHandler: function(form) {
        //whatever needs to be done
        console.log(form);
    }
}

I've used this approach successfully in 4.1.0 and 4.1.1

查看更多
成全新的幸福
4楼-- · 2020-05-27 11:16

It really should be

Assessor.controller.Auth.prototype.finishLogin.apply(this, arguments)

or something along these lines (in order to have a correct this reference that points to the 'owner' of the method, the controller object)

However, why do you use this unorthodox way to call the current controller's method. Just set the scope for the success callback, then call this.finishLogin().

form.submit({
    success : function(form, action) {
        // THIS IS THE FUNCTION FROM THE CURRENT CONTROLLER
        this.finishLogin();
        ...
    },
    scope: this
});

Also, you can retrieve another controller instance using Controller#getController.

this.getController('Assessor.controller.quiz').setupAssignment();

Then, if your controller methods are not depending on each other, you could make them both listen to the same event.

Another solution is to fire a custom event once the login is finished. You could do that on the application object

this.application.fireEvent('logincomplete');

and in your controller's init method:

this.application.mon('logincomplete', this.setupAssignment, this);

Please note that you cannot listen to those events via Controller#control - see Alexander Tokarev's blog post for a patch to Ext to achieve this.

查看更多
兄弟一词,经得起流年.
5楼-- · 2020-05-27 11:24

There is no standard way to fire events between controllers, but it's possible with some custom hacks. See my recent blog post.

查看更多
等我变得足够好
6楼-- · 2020-05-27 11:26

You should use a MessageBus if you have to send events between controllers:

Ext.define('MyApp.utils.MessageBus', {
        extend : 'Ext.util.Observable'
});

store the message bus in a global var

MsgBus = Ext.create('MyApp.utils.MessageBus');

Where you have to send events:

MsgBus.fireEvent('eventName',eventArg_1,eventArg_2);

Where you have to receive events:

MsgBus.on('eventName', functionHandler,scope); //scope is not mandatory
...
functionHandler:function(eventArg_1,eventArg_2){
...
//do whatever you want
...
}
查看更多
登录 后发表回答