AngularAMD + ui-router +动态控制器名称?

Say*_*jee 7 angularjs angular-ui-router angular-amd

我正在尝试在我的应用程序中编写一个通用路由,并根据路径参数动态解析视图和控制器名称.

我有以下代码:

$stateProvider.state('default', angularAMD.route({
    url: '/:module/:action?id',

    templateUrl: function (params) {
        var module = params.module;
        var action = module + params.action.charAt(0).toUpperCase() 
                            + params.action.substr(1);

        return 'app/views/' + module + '/' + action + 'View.html';
    },

    controller: 'userController',
}));
Run Code Online (Sandbox Code Playgroud)

但是,我无法找到一种动态解析控制器名称的方法.我尝试使用这里resolve描述的,但ui-router似乎处理不同于angular-route的解决方案.

有什么指针吗?

编辑:我已经尝试过使用controllerProvider但它对我不起作用(例如,下面的代码只返回一个硬编码的控制器名称来测试它是否真的有效):

controllerProvider: function () {
    return 'userController';
}
Run Code Online (Sandbox Code Playgroud)

给我以下错误:

错误:[ng:areq]参数'userController'不是函数,未定义 http://errors.angularjs.org/1.3.3/ng/areq?p0=userController&p1=not%20aNaNunction%2C%20got%20undefined

Rad*_*ler 19

这是工作plunker的链接.

我们需要UI-Router的两个功能:

  • 解决(加载缺少的js代码片段)
  • controllerProvider(参见下面文档中的引用)

angularAMD - main.js定义

这将是我们的main.js,其中包含智能转换controllerName - controllerPath:

require.config({

    //baseUrl: "js/scripts",
    baseUrl: "",

    // alias libraries paths
    paths: {
        "angular": "angular",
        "ui-router": "angular-ui-router",
        "angularAMD": "angularAMD",

        "DefaultCtrl": "Controller_Default",
        "OtherCtrl": "Controller_Other",
    },

    shim: {
        "angularAMD": ["angular"],
        "ui-router": ["angular"],
    },

    deps: ['app']
});
Run Code Online (Sandbox Code Playgroud)

控制器:

// Controller_Default.js
define(['app'], function (app) {
    app.controller('DefaultCtrl', function ($scope) {
        $scope.title = "from default"; 
    });
}); 

// Controller_Other.js
define(['app'], function (app) {
    app.controller('OtherCtrl', function ($scope) {
        $scope.title = "from other";
    });
});
Run Code Online (Sandbox Code Playgroud)

app.js

首先,我们需要一些将param(例如id)转换为控制器名称的方法.为了我们的测试目的,让我们使用这个天真的实现:

var controllerNameByParams = function($stateParams)
{
    // naive example of dynamic controller name mining
    // from incoming state params

    var controller = "OtherCtrl";

    if ($stateParams.id === 1) {
        controller = "DefaultCtrl";
    }

    return controller;
}
Run Code Online (Sandbox Code Playgroud)

.state()

这最终将是我们的州定义

$stateProvider
    .state("default", angularAMD.route({
        url: "/{id:int}",
        templateProvider: function($stateParams)
        {
            if ($stateParams.id === 1)
            {
                return "<div>ONE - Hallo {{title}}</div>";
            }
            return "<div>TWO - Hallo {{title}}</div>";
        },
        resolve: {
            loadController: ['$q', '$stateParams',
                function ($q, $stateParams)
                {
                    // get the controller name === here as a path to Controller_Name.js
                    // which is set in main.js path {}
                    var controllerName = controllerNameByParams($stateParams);

                    var deferred = $q.defer();
                    require([controllerName], function () { deferred.resolve(); });
                    return deferred.promise;
                }]
        },
        controllerProvider: function ($stateParams)
        {
            // get the controller name === here as a dynamic controller Name
            var controllerName = controllerNameByParams($stateParams);
            return controllerName;
        },
    }));
Run Code Online (Sandbox Code Playgroud)

在这个工作示例中查看此处

文件

如下所述:$ stateProvider,state(name, stateConfig)我们可以使用controllercontrollerProvider.一些摘自文档:

controllerProvider

...

controller (可选) stringfunction

如果作为字符串传递,则应与新相关范围或已注册控制器的名称相关联的控制器fn.可选地,可以在此声明ControllerAs.

controller: "MyRegisteredController"

controller:
"MyRegisteredController as fooCtrl"}

controller: function($scope, MyService) {
$scope.data = MyService.getData(); }
Run Code Online (Sandbox Code Playgroud)

controllerProvider (可选) 功能

可注入的提供程序函数,返回实际的控制器或字符串.

controllerProvider:
  function(MyResolveData) {
    if (MyResolveData.foo)
      return "FooCtrl"
    else if (MyResolveData.bar)
      return "BarCtrl";
    else return function($scope) {
      $scope.baz = "Qux";
    }
  }
Run Code Online (Sandbox Code Playgroud)

...

解决

resolve (可选) 对象

map<string, function>应该注入控制器的可选依赖项.如果这些依赖项中的任何一个是promise,路由器将等待它们在控制器实例化之前解析ALL ...

即,让我们使用controllerProvider:

...动态解析控制器名称...

如果你设法到达这里,也许你想用RequireJS检查另一个类似的解决方案 - angular-ui-router with requirejs,延迟加载控制器

  • 好的,我为你创建了一个;)使用UI-Router我们几乎可以做任何事情;)享受它 (3认同)
  • w00t!这适合我.谢谢!:)你有一个美好的一周! (2认同)