6
votes

after generating a Workspace using Sencha Cmd and create Two different app, i just want to Run the first app and then after clicking a button,it calls the second app :) Like A main app calling another sub-app is there a way to do it ? thx for your help

2
what should be the result? you call a static service (update someting) or you need nice response ?d.raev
The first app will be an empty panel and a button.when i click the button ,the second app will be loaded on the panel (of the first app).Hachicha Moktar

2 Answers

19
votes

You can develop separated modules that can work together with no problems. Both concepts are no in conflict at all.

Let me share my experience here. When we started in our current project (from the scratch) there were other two teams developing another two applications which after some time we should 'integrate' them in just one big app. You don´t have to be a genius to predict the ending result, right? Things got worse when we heard customer wanted more parallel work (more teams developing modules).

The first idea was using iframes but the PoC demonstrated it was a bad idea so, we stopped the machine and started designing a pluggable architecture. We did it well because currently we are able to load modules (we called it plugins) developed in an isolated way easily. For example, take a look at how our folder structure looks like:

enter image description here

And this is the metadata where we set the modules we want to load: enter image description here

This has a lot of advantages:

  • modules can be developed in parallel,
  • modules can be tested isolated,
  • modules can be loaded dynamically, enabled or disabled

Of course, this is not something extjs provides out of the box but you can do it because it worth.

So, short answer: your problem is not the application´s size but its struture instead. Follow the recommended MVC pattern with a custom folder structure as we do.

Update:

About the plugins metadata. The application main controller has only one responsability: load the plugins. This is done with this code:

discoverPlugins: function () {
    var me = this;
    Ext.each(plugins(), function (d) {
        me.loadPluginController(d.controller);
    });

    App.History.notifyAppLoaded();
},

loadPluginController: function (controllerName) {
    try {
        var controller = App.current.getController(controllerName);
        controller.init(App.current);
    } catch (e) {
        console.log(controllerName + ' controller couldn\'t be loaded.' + e);
    }
},

And every plugin controller acts as a dispatcher, this is, there is a history component listening the url (in the address bar) and when it changes, iterates plugin by plugin asking for handle the url. The process ends when a plugin is able to handle the requested url.
This is the dispatcher configuration for the 'operations' plugins:

constructor: function () {
    this.callParent(arguments);
    this.router.set({
        '!/operations/product/permissions/definition': this.viewPermissionsDefinition,
        '!/operations/product/accesslist/create': this.createProductAccessList,
        '!/operations/product/accesslist/{id}/edit': this.editProductAccessList,
        '!/operations/product/accesslist/{id}': this.viewProductAccessList,
        '!/operations/product/accesslist': this.viewProductAccessList,
        '!/operations/{...}': this.notFound,
        '!/operations': this.root
    });
} 

And This is the navigate method of the history class code:

navigate: function (token) {
    var me = this,
        handled;

    if (token) {
        handled = false;
        for (var i = 0; i < me.routers.length; i++) {
            if (me.routers[i].processToken(token)) {
                handled = true;
                break;
            }
        }

        if (!handled) {
            App.current.fail(404, 'Resource not found.');
        }
    } else {
        App.current.gotoUrl('/servicedesk/search');
    }
},

One important point is plugins only have a reference to one shared component: the center area where they are rendered:

refs: [
    { ref: 'main', selector: '#center-panel' }
],

This reference is inherited by all the plugin controllers which are subclasses of a 'AbstractPluginController'. This is important because is the only thing modules know about their hoster. And this is why we can develop in parallel.

About the AbstractPluginController, this same class has some core functionalities useful for all the plugin controllers, for example, in order to load all theirs controllers/views/models when are required and not before that, this class implements the dynamic controllers loading as follow:

createControllerGetters: function (controllers) {
    var me = this;
    controllers = Ext.Array.from(controllers);
    Ext.Array.each(controllers, function (controllerName) {
        var parts = controllerName.split('.'),
            idx = parts.indexOf('controller'),
            significants = parts.slice(idx + 1),
            name = significants.map(function (e) { return Ext.String.capitalize(e); }).join(''),
            fn = 'get' + name + 'Controller';

        if (!me[fn]) {
            me[fn] = Ext.Function.pass(me.getController, [controllerName], me);
        }
    });
},

getController: function (controllerName) {
    this.controllerCache = this.controllerCache || {};
    var me = this,
        cached = me.controllerCache[controllerName];

    if (!cached) {
        me.controllerCache[controllerName] = cached = App.current.getController(controllerName);
        if (cached) {
            cached.init();
            cached.on('beforedestroy', function () {
                me.controllerCache[ref] = null;
            });
        }
    }

    return cached;
},

This allows us to specify the list of subcontrollers (because the main controllers is just an initializer and dispatch) the module has, and allows us to create them on demand.

controllers: [
    'Operations.controller.ProductAccessListViewer',
    'Operations.controller.ProductAccessListEditor',
    'Operations.controller.ProductAccessListCreator'
],

Summarizing: I think the main points are these:

  1. modules don´t have to know anything about the host application.
  2. navigation/communication through links, mostly
  3. integration performed by the host using metadata (plugins can expose extra metadata too)
  4. lazy loading of controllers (they do the something with their own views)

I hope this gives you an idea. There are lots of details an some tricks to integrate them but basically, what i want to show here is a modular application can be (or should be) developed with extjs with just a little of extra effort.

0
votes

This topic has been brought up before. Check out suggestions here: Using more than one controller with ExtJS 4 MVC