Using the AngularUI Router to dynamically load controllers

那年仲夏 提交于 2019-12-22 10:36:29

问题


I'm using ui-router in an app that will have dozens of templates. Each template will have a controller.

From what I've been reading, something like this (to setup a route) ought to work:

.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('start', {
      url: '/start',
      templateUrl: 'partials/start.html',
      controller: 'StartCtrl'
    })
});

That's assuming StartCtrl was previously defined. The app will eventually have dozens of controllers, and don't want the overhead of downloading all of them at once. How can I load a controller only when the template is requested?


回答1:


I use RequireJS for this. And an in a provider, say lazyProvider:

In your lazy provider...

this.resolve = function(controller){
    return { myCtrl: ['$q',function ($q){
            var defer = $q.defer();
            require(['/app/controllers/'+controller,'myApp'],function(ctrl,myApp){
                myApp.register.controller(controller,ctrl);
                defer.resolve();

            }
            return defer.promise;
        }]
    };
};

In your ui-router resolve: property do:

resolve: lazyProvider.resolve('myCtrl');

You'll need to expose provider registers on your app so you can register them later, like:

myApp.config(function($urlRouterProvider, $stateProvider,
          $controllerProvider, $compileProvider, $filterProvider,$provide){
    //If your myApp isn't already a module...
    define('myApp',[],function(){return myApp});
    myApp.register = {
        controller: $controllerProvider.register,
        directive: $compileProvider.directive,
        filter: $filterProvider.register,
        factory: $provide.factory,
        service: $provide.service,
        constant: $provide.constant
    }

And your controllers:

define(['/dependencies'],function(deps){
    function MyCtrl($scope){...}
    return MyCtrl;
}

This is essentially what Dan Wahlin has shared here




回答2:


After playing around with @calebboyd sample, I got it working using System.js and ES6. What I liked about this implementation is that using ES6 modules, everything depends only on the file names which are already unique, so you don't need to care about controller names conflicting or even naming them. Controllers are anonymous.

This implementation assumes you have a folder "pages" with template/controller pairs like this:

/pages
  /page1.html
  /page1.js
  /page2.html
  /page2.js

Once you access /#pages/page1, it will load both the template and the controller dynamically.

Here is your "app.js":

import angular from 'angular';
import 'angular-ui-router';

angular.module('app', ['ui.router'])
  .config(($stateProvider, $urlRouterProvider, $controllerProvider) => {

    // save reference to the register method, so we can use inside the 'resolve'
    var registerController = $controllerProvider.register;

    // register a single state that takes the page name as a parameter
    $stateProvider
      .state('pages', {
        url: "/pages/:name",

        // the url and the controller name are dynamically created
        templateUrl: $stateParams => "pages/" + $stateParams.name + ".html",
        controllerProvider: $stateParams => $stateParams.name + '_DynamicController as vm',

        resolve: {

          'ctrl': ($stateParams, $q) => {

            var script = 'pages/' + $stateParams.name;
            var controllerName = $stateParams.name + '_DynamicController';

            // once System.js loads the module, we register using the
            // saved registerController function with the dynamic name
            return System.import(script)
              .then(ctrl => registerController(controllerName, ctrl['default']));
          }
        }
      });
  });

Here is a sample controller in "page1.js":

export default class {
  constructor() {
    this.data = "inside the controller";
  }
}

Sample template in "page1.html":

<h1>Page1 Template</h1>
Loaded: {{ vm.data }}


来源:https://stackoverflow.com/questions/21247327/using-the-angularui-router-to-dynamically-load-controllers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!