Hello,

On a precedent topic ( http://www.sencha.com/forum/showthre...315&viewfull=1 ), I was looking for a way to load dynamically classes from Ajax Request.

Browsing the forum, I found a very interesting project from Mitchell Simoens (you can find it here : https://github.com/mitchellsimoens/SubAppDemo ). Thank you Mitchell for sharing this.

Well, I studied it the all day and got it almost work on my application, I modified the code from Mitchell to get it work on my app.

Let me share this to you :

SubApplication class (modified, initial code from Mitchell)

Code:
Ext.define('Ext.apm.SubApplication', { //apm is my name space, I put this file in /myapp/apm
    extend: 'Ext.app.Controller',


    requires: [
        'Ext.ModelManager',
        'Ext.data.Model',
        'Ext.data.StoreManager',
        'Ext.ComponentManager',
       // 'Ext.apm.EventBus' //forced to comment this to start...I'll speak of this later in the post
    ],


    /**
      * @cfg {Ext.app.Application} app Reference to the global Ext.app.Application instance
      */
    /**
      * @cfg {String} id ID of the SubApplication.
      */


    /**
      * @cfg {Array} controllers Array of Controller names to create.
      */
    /**
      * @cfg {Object} dependencies Object holding Arrays for CSS and JS files to load.
      * JS files will automatically be destroyed once all JS files are loaded.
      * CSS files will be automatically destroyed when SubApplication is destroyed
      */
    dependencies      : {
        css : [],
        js  : []
    },
    /**
      * @cfg {Boolean/Ext.LoadMask} loadMask true to use a Ext.LoadMask while loading dependencies.
      * Can also accept a config Object of Ext.LoadMask
      */
    loadMask          : true,
    /**
      * @cfg {String} loadingCls CSS name(s) to apply to the message div of Ext.LoadMask
      */
    loadingCls        : '',
    /**
      * @cfg {String} loadingText Text to show in the Ext.LoadMask
      */
    loadingText       : 'Loading...',
    /**
      * @cfg {Boolean} loadingUseMsg true to show a message in the Ext.LoadMask
      */
    loadingUseMsg     : true,
    /**
      * @cfg {Number}removeJSFileDelay Time in milliseconds to delay destroying JS files after all have been loaded
      */
    removeJSFileDelay : 100,


    scope             : undefined,


    /**
       * Function that will be called before the launch function but after all dependencies
       * have been loaded and Controllers created.
       * @property beforelaunch
       * @type Function
       */
    beforeLaunch : Ext.emptyFn,
     /**
       * Function that will be called after everything has been set up. Use this function
       * to create the SubApplication views.
       * NOTE: Return the main view as SubApplication will listen for it's destroy event to destroy the SubApplication.
       * @property launch
       * @type Function
       * @return {Ext.Component} Return the main view as SubApplication will listen for it's destroy event to destroy
       * the SubApplication.
       */
    launch       : Ext.emptyFn,


    constructor: function(config){
        config = config || {};
        var me          = this;
        var app         = config.app;
        
        var  controllers = Ext.Array.from(config.controllers);




    
        Ext.apply(config, {
            documentHead : Ext.getHead(),
            id           : config.id,


           // eventbus     : app.eventbus, //forced to comment


            //private
            //holds loaded JS files to remove after loading file
            loadedJS     : Ext.create('Ext.util.MixedCollection'),
            //private
            //holds loaded CSS files to remove on destruction
            loadedCSS    : Ext.create('Ext.util.MixedCollection'),
        });


        
        me.callParent(arguments);
        
        Ext.apply(me, {
            appControllers : controllers,
            controllers    : Ext.create('Ext.util.MixedCollection')
        });
        
        me.init();
       
    },


    init: function() {
        
        var me           = this,
            dependencies = me.config.dependencies, //needed to add config, cuz of ST 2 ?
            css          = dependencies.css,
            js           = dependencies.js,
            loadMask     = me.config.loadMask,
            cfg;
           
 /* pour le masque on verra apres  = I'll see later with that
            if (loadMask) {
            cfg = Ext.isObject(loadMask) ? loadMask : {
                    msg    : me.loadingText,
                    msgCls : me.loadingCls,
                    useMsg : me.loadingUseMsg
                };


            me.loadMask = loadMask = Ext.create('Ext.LoadMask', Ext.getBody(), cfg);
            loadMask.show();
        }
        ***/
        Ext.each(css, function(file) {
           me.loadCSSFile(file);
        });
        
        Ext.each(js, function(file) {
            me.loadJSFile(file);
        });
        
       
       
          
    },






    
    loadCSSFile: function(file) {
        var me   = this,
            head = me.config.documentHead, //needed to add .config
            css  = document.createElement('link');


        Ext.apply(css, {
            href : file,
            rel  : 'stylesheet',
            type : 'text/css'
        });


        head.appendChild(css);
        me.loadedCSS.add(Ext.get(css));
    },


    //ajout de fichier js (par utile je pense, on va voir);
    loadJSFile: function(file) {
        var me     = this,
            head   = me.config.documentHead,
            script = document.createElement('script');


        Ext.apply(script, {
            src  : file,
            type : 'text/javascript',
            
            onload : Ext.Function.createDelayed(me.handleFileLoad, me.removeJSFileDelay, me, [script]),
            onreadystatechange : function() {
                if (this.readyState === 'loaded' || this.readyState === 'complete') {
           
                    me.handleFileLoad(script);
                }
            }
        });


        head.appendChild(script);
    },


    handleFileLoad: function(script) {
        script.onload = null;
        script.onreadystatechange = null;
        script.onerror = null;


        var me       = this,
            loadedJS = me.config.loadedJS;


        loadedJS.add(Ext.get(script));
        me.checkJSDependencyState();
    },


    checkJSDependencyState: function() {
        var me           = this,
            dependencies = me.config.dependencies,
            js           = dependencies.js,
            jsLen        = js.length,
            loadedJS     = me.config.loadedJS,
            loadedLen    = loadedJS.getCount();


        if (jsLen === loadedLen) {
            loadedJS.each(function(file) {
                me.removeFile(file);
                loadedJS.remove(file);
            });


            me.onBeforeLaunch();
        }
    },


    addController: function(controller, skipInit) {
      
        if (Ext.isDefined(controller.name)) {
            var name = controller.name;
            delete controller.name;


            controller.id = controller.id || name;


            controller = Ext.create(name, controller);
        }


        var me          = this,
            controllers = me.controllers;
        controllers.add(controller);


        if (!skipInit) {
            controller.init();
        }


        return controller;
    },


    removeController: function(controller, removeListeners) {
        removeListeners = removeListeners || true;


        var me          = this,
            controllers = me.controllers;


        controllers.remove(controller);


        if (removeListeners) {
            var bus = me.eventbus;


            bus.uncontrol([controller.id]);
        }
    },




    addSubApplication: function(subapp) {
        
        var me      = this,
            app     = me.config.app,
            subapps = app.subApplications;


        subapps.add(subapp);


        return subapp;
    },


    removeSubApplication: function(subapp) {
        var me      = this,
            app     = me.config.app, //config needed
            subapps = app.subApplications;


        subapps.remove(subapp);
    },


    removeFile: function(file) {
        console.log('zermove file');
        Ext.destroy(file);
    },


    onBeforeLaunch: function() {
        
        var me          = this,
            app         = me.config.app,
            controllers = me.appControllers,
            loadMask    = me.config.loadMask,
            controller, subapp;
           
        if (app) {
            Ext.each(controllers, function(controlName) {
                controller = {
                    application : app,
                    name        : controlName
                };
                controller = me.addController(controller);
            });


            delete me.appControllers;


            Ext.applyIf(app, {
                subApplications : Ext.create('Ext.util.MixedCollection')
            });


            subapp = me.addSubApplication(me);
        }
        me.beforeLaunch.call(me.scope || me);


        /**on cache le mask 
        if (loadMask) {
            loadMask.hide();
        }
        */
        
    var cmp =me.config.launch();//this line work
      //  var cmp = me.launch.call(me.scope || me);//this line doesn't work


        if (cmp) {
            me.cmp = cmp;
            cmp.on('destroy', me.handleSubAppDestroy, me);
        }
    },


    handleSubAppDestroy: function(cmp) {
        var me             = this,
            app            = me.app,
            bus            = app.eventbus,
            appControllers = app.controllers,
            controllers    = me.controllers,
            cssFiles       = me.loadedCSS,
            deleteThis     = false,
            appController, idx;


        controllers.each(function(controller) {
            me.removeController(controller);
        });


        cssFiles.each(function(file) {
            me.removeFile(file);


            cssFiles.remove(file);
        });


        me.removeSubApplication(me);


        me.loadedCSS = null;
        me.loadedJS  = null;
        me = null;
    }
});
and here is how I use this class:

Code:
                                                     var me     = this,
                                app    = me.getApplication(),//changed for ST2
                              
                                    subapp = Ext.create('Ext.apm.SubApplication',{
                                    application : app, //otherwise you get a getRouter of undefined error...
                                    app          : app,
                                    id           : 'MyWidget.controller.View',
                                    loadMask     : true,
                                    loadingText  : 'Loading Test...',
                    
                                    controllers : [
                                        'MyWidget.controller.Controller'
                                    ],
                    
                                    dependencies : {
                                        css : [
                                            'http://myserver/mywidget/mycss.css'
                                        ],
                                        js  : [
                           'http://myserver/mywidget/mycode.js',//contains all the widget code
                                        ]
                                    },
                    
                                    launch: function() {
                                        
                                        var widgetPanel = Ext.create('AirformSuivi.view.Formmonitor', {
                                            app : me
                                        });
                                       
                                        me.getPortal().add(widgetPanel); //portal is the panel
                                        
                                        me.getPortal().setActiveItem(1);//with a layout card
                                    }
                                });

Well no problem with that, that works ! I able to get code from server side, and I can instanciate the controller (=> events ok, etc...)

The issue is when removing Controller : the class EventBus doesn't exist in Sencha Touch 2 (that's why I commented it). Now I don't see how I can easily destroy the controller,

Any Ideas (Mitchell ?)

Thank you very much in advance