7

EXTJS 4.1

I have run into a bit of a conundrum and would love to hear some other developers input on this scenario regarding ExtJS events and controller methods. I understand this topic has been covered and debated on numerous occasions but I feel that it could use a bit more delving into.

As is standard practice, I define event listeners in my Controller's init() method declaration as follows:

Ext.define("My.controller.Awesome", {
init: function(application){
    /** Observe some Views */
    this.control({
        'my-awesome-view #saveButton':{
             click: this.saveMyData
         }
    });

    /** Listen for Events, too! */
    this.on({
        showAwesomeView: this.showMyAwesomeView
    });

    /** Application events, what fun! */
    this.application.on({
        showThatAwesomeView: this.showMyAwesomeView
    });
}

Now, as I merrily go about coding some functionality in some other controller, I find myself needing to call showMyAwesomeView in My.controller.Awesome. I can do this in a few different ways...

Ext.define("My.controller.Other", {

    /* ... class definition */

    someImportant: function(){

        // I can do this (Approach #1)
        this.application.getController("Awesome").showMyAwesomeView();

        // Or I can do this (Approach #2)
        this.application.getController("Awesome").fireEvent("showAwesomeView");

        // Last but not least, I can do this (Approach #3)
        this.application.fireEvent("showThatAwesomeView");
    }
});

To me, Approach #3 feels the most 'right'. My problem is that if I haven't instantiated the My.controller.Awesome before, the init() method has not been run yet and therefore there are no listeners established, so the fired event goes off into mystery land never to be heard of again.

I have overloaded Ext.application.getController() to call controller.init() before returning controller, therefore a controller has its init method called as soon as it is loaded (typically as a dependency in another controller). Is this bad?

In order to save on load time (my application is quite large) my controllers and their dependencies are loaded on an as-needed basis. Therefore, the majority of my controllers (and views, and data stores) are not instantiated when my application first boots therefore not init()'ed which makes firing application-wide events quite cumbersome.

I feel like I may be missing something big here, or maybe I just need to bite the bullet and ensure my controllers have been init'd before firing events. I suppose I could also put an absolutely horrific number of event listeners in the main application file and handle init'ing controllers before calling their methods accordingly, but this seems very sloppy and difficult to maintain.

Any input would be greatly appreciated, thank you for your time!

John Hall
  • 1,346
  • 13
  • 27
  • Interesting, I suppose you feel method 3 is best because it's most decoupled, controller 2 doesn't have to care which controller should perform the action it requires. But, unless the controller is already available, someone has to know.. Maybe you can create some sort of routing table at the application level (which controller listen to which events), and have fireEvent init the required controller? – Amit Aviv May 13 '13 at 16:45
  • @AmitAviv I briefly described the routing idea in my question, but it seems very sloppy to have a massive list of listeners in the main application file solely to ensure a controller is instantiated before calling the required method. I would rather instantiate the controller manually (in the callee controller) before firing the event. Thanks for your input! – John Hall May 13 '13 at 17:13
  • 1
    I don't mean a massive list of listeners, I mean a table, keys are event names, values are controller names.. fireEvent can be overloaded to read the table and init the required controller based on the table. I'm not sure it's a very good solution, but I don't see a magical way to maintain the decoupling & lazy loading & having no one knowing about the "event-controller" relationship.. – Amit Aviv May 13 '13 at 17:21
  • 1
    I mean O as in Awesome question +1.. – aMazing Apr 29 '14 at 04:34

2 Answers2

3

Approach #3 (this.application.fireEvent('showThatAwesomeView')) is a great solution. The use of application events results in controllers that have no assumptions about what other logic may be added or removed from the application related to this event.

Regarding your concern about controllers having been instantiated in time to be correctly bound to events, use of the Ext.app.Application controller will eliminate this. The App controller initializes all specified controllers when the App initializes. You noted a concern about start-up time related to the number of controllers. I have worked on many single page apps that have dozens and even hundreds of controllers in some cases. Keeping any init logic to a minimum should reduce any noticeable slowdown. Minified and combined scripts in place of on-demand loading has worked well to keep app start-up very fast.

Avoiding the getController method is good practice. Application logic tends to be better organized when using application events in place of logic that tightly couples controllers with each other.

John Rice
  • 1,737
  • 8
  • 14
  • 1
    I wholeheartedly agree with your suggestions, though I am still concerned a bit with having to load all my controllers on app launch. As the loading of data stores is generally the bottleneck (I think?), perhaps I need to devise a method to only load certain data stores, and load others only when needed. I'm going to leave the question as unanswered for now, but I will mark your answer as correct pending any other answers. Thanks very much for the input! – John Hall May 13 '13 at 18:30
  • OK, great. Deferring data load is also very helpful to speed initial application load. – John Rice May 13 '13 at 19:11
  • I accepted your answer, thanks again. I posted a somewhat related question regarding complex save operations if you care to offer your input :) http://stackoverflow.com/questions/16551901/extjs-and-complex-save-operations – John Hall May 16 '13 at 19:13
0
Ext.define('UD.controller.c1', {
    extend: 'Ext.app.Controller',
    refs: [
            {
                selector: 'viewport',
                ref: 'userview'
            }
          ],
    init: function() {
        console.log("initincontroller!!");
        this.control({
            'viewport > panel': {
                render: this.onPanelRendered
            }
        });
    },
    onPanelRendered:function(){
        alert("rendered");
        UD.getApplication().fireEvent('myevent');
    }
});



Ext.define('UD.controller.c2', {
    extend: 'Ext.app.Controller',
    refs: [
            {
                selector: 'viewport',
                ref: 'userview'
            }
          ],
    init: function() {
        console.log("initincontroller!!");
            UD.getApplication().on({
                myevent : this.doSomething
             });
    },
    doSomething:function(){
        alert("controller2");
    }
});
Balrrazh
  • 11
  • 1