UI-router 中的 ControllerProvider 导致错误
ControllerProvider in UI-router results in error
我有一个 ui-router
StateProvider
,需要根据外部数据在控制器和视图之间进行选择,所以我使用了 TemplateProvider
和 ControllerProvider
。
如果我只有 TemplateProvider
一切正常,但是当我添加 ControllerProvider
时我得到这个错误:
Error: [ng:areq] Argument 'fn' is not a function, got Object
http://errors.angularjs.org/1.3.1/ng/areq?p0=fn&p1=not%20aNaNunction%2C%20got%Object
at REGEX_STRING_REGEXP (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:80:12)
at assertArg (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:1577:11)
at assertArgFn (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:1587:3)
at annotate (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:3417:5)
at invoke (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:4096:21)
at Object.instantiate (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:4129:23)
at http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:8320:28
at compile (http://localhost:48510/Scripts/Vendor/AngularUIRouter/angular-ui-router.js:3897:28)
at invokeLinkFn (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:8081:9)
at nodeLinkFn (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:7593:11)
看起来像一些 undefined
serviceName
可能(它说得到了对象,但它看起来像 undefined
但我不擅长调试 AngularJs
)
这是我的代码:
.state('abstractParent.childState', {
url: '/childState',
controllerProvider: ['myService', function (myService) {
return myService
.isSpecificMember()
.then(function (result) { //this returns a promise of a bool.
if (result.data) {
return 'SpecificController';
} else {
return 'GeneralController';
}
})
}],
templateProvider: ['myService', '$templateFactory',
function (myService, $templateFactory) {
return myService.isSpecificMember().then(function(result) {
if(result.data)
{
return $templateFactory.fromUrl('SpecificView');
} else {
return $templateFactory.fromUrl('GenericView');
}
})
}],
resolve: {
thing: ['thingService', function (thingService) {
//this is only used in one of the controllers.
return thingService.getThing();
}]
}})
编辑
根据 Radim Köhlers 的回答所做的更改
.state('abstractParent.childState', {
url: '/childState',
resolve: {
controllerName: ['myService', function (myService) {
return myService.isSpecificMember().then(function (result) { //this returns a promise of a bool.
if (result.data) {
return 'SpecificController';
} else {
return 'GeneralController';
}
})
}],
thing: ['thingService', function (thingService) { //this is only used in one of the controllers.
return thingService.getThing();
}]
},
controllerProvider: ['controllerName', function (controllerName) {
return controllerName;
}],
templateProvider: ['myService', '$templateFactory', function (myService, $templateFactory) {
return myService.isSpecificMember().then(function(result) {
if(result.data)
{
return $templateFactory.fromUrl('SpecificView');
} else {
return $templateFactory.fromUrl('GenericView');
}
})
}]
})
新错误:
Error: [$injector:unpr] Unknown provider: controllerNameProvider <- controllerName
http://errors.angularjs.org/1.3.1/$injector/unpr?p0=controllerNameProvider%20%3C-%20controllerName
at REGEX_STRING_REGEXP (1-angular.js:80)
at 1-angular.js:3930
at Object.getService [as get] (1-angular.js:4077)
at 1-angular.js:3935
at getService (1-angular.js:4077)
at Object.invoke (1-angular.js:4109)
at angular-ui-router.js:3465
at processQueue (1-angular.js:12901)
at 1-angular.js:12917
at Scope.$get.Scope.$eval (1-angular.js:14110)
解决方案
这至少需要 angular-ui-router.js
的 0.2.14
版本
重点是,controllerProvider
必须 return object 表示 controller
或 string
(它的名字)
http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$stateProvider
stateConfig.controllerProvider
(optional) function
Injectable provider function that returns the actual controller or string.
所以,我们不能return承诺...
但是有一个解决办法:
我们可以使用内置功能 resolve - 执行异步操作,并使 controllerProvider
成为英雄 - 通过使用它:
resolve: {
controllerName: ['$stateParams', '$timeout','$q',
function ($stateParams, $timeout, $q)
{
var deferred = $q.defer();
$timeout(function(){
deferred.resolve('MyLazyRevealedCtrl');
},250);
return deferred.promise;
}],
},
controllerProvider:['controllerName', function (controllerName)
{
return controllerName;
}],
我们可以看到的是只有一个计时器的简化示例(扮演异步 .then()
的角色)。它会等待一段时间,然后 return 解析控制器名称。
controllerProvider
然后(一旦全部解决)只需要结果,return将其作为字符串。
检查一下here
我有一个 ui-router
StateProvider
,需要根据外部数据在控制器和视图之间进行选择,所以我使用了 TemplateProvider
和 ControllerProvider
。
如果我只有 TemplateProvider
一切正常,但是当我添加 ControllerProvider
时我得到这个错误:
Error: [ng:areq] Argument 'fn' is not a function, got Object
http://errors.angularjs.org/1.3.1/ng/areq?p0=fn&p1=not%20aNaNunction%2C%20got%Object
at REGEX_STRING_REGEXP (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:80:12)
at assertArg (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:1577:11)
at assertArgFn (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:1587:3)
at annotate (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:3417:5)
at invoke (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:4096:21)
at Object.instantiate (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:4129:23)
at http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:8320:28
at compile (http://localhost:48510/Scripts/Vendor/AngularUIRouter/angular-ui-router.js:3897:28)
at invokeLinkFn (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:8081:9)
at nodeLinkFn (http://localhost:48510/Scripts/Vendor/Angular/1-angular.js:7593:11)
看起来像一些 undefined
serviceName
可能(它说得到了对象,但它看起来像 undefined
但我不擅长调试 AngularJs
)
这是我的代码:
.state('abstractParent.childState', {
url: '/childState',
controllerProvider: ['myService', function (myService) {
return myService
.isSpecificMember()
.then(function (result) { //this returns a promise of a bool.
if (result.data) {
return 'SpecificController';
} else {
return 'GeneralController';
}
})
}],
templateProvider: ['myService', '$templateFactory',
function (myService, $templateFactory) {
return myService.isSpecificMember().then(function(result) {
if(result.data)
{
return $templateFactory.fromUrl('SpecificView');
} else {
return $templateFactory.fromUrl('GenericView');
}
})
}],
resolve: {
thing: ['thingService', function (thingService) {
//this is only used in one of the controllers.
return thingService.getThing();
}]
}})
编辑
根据 Radim Köhlers 的回答所做的更改
.state('abstractParent.childState', {
url: '/childState',
resolve: {
controllerName: ['myService', function (myService) {
return myService.isSpecificMember().then(function (result) { //this returns a promise of a bool.
if (result.data) {
return 'SpecificController';
} else {
return 'GeneralController';
}
})
}],
thing: ['thingService', function (thingService) { //this is only used in one of the controllers.
return thingService.getThing();
}]
},
controllerProvider: ['controllerName', function (controllerName) {
return controllerName;
}],
templateProvider: ['myService', '$templateFactory', function (myService, $templateFactory) {
return myService.isSpecificMember().then(function(result) {
if(result.data)
{
return $templateFactory.fromUrl('SpecificView');
} else {
return $templateFactory.fromUrl('GenericView');
}
})
}]
})
新错误:
Error: [$injector:unpr] Unknown provider: controllerNameProvider <- controllerName
http://errors.angularjs.org/1.3.1/$injector/unpr?p0=controllerNameProvider%20%3C-%20controllerName
at REGEX_STRING_REGEXP (1-angular.js:80)
at 1-angular.js:3930
at Object.getService [as get] (1-angular.js:4077)
at 1-angular.js:3935
at getService (1-angular.js:4077)
at Object.invoke (1-angular.js:4109)
at angular-ui-router.js:3465
at processQueue (1-angular.js:12901)
at 1-angular.js:12917
at Scope.$get.Scope.$eval (1-angular.js:14110)
解决方案
这至少需要 angular-ui-router.js
0.2.14
版本
重点是,controllerProvider
必须 return object 表示 controller
或 string
(它的名字)
http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$stateProvider
stateConfig.controllerProvider
(optional) functionInjectable provider function that returns the actual controller or string.
所以,我们不能return承诺...
但是有一个解决办法:
我们可以使用内置功能 resolve - 执行异步操作,并使 controllerProvider
成为英雄 - 通过使用它:
resolve: {
controllerName: ['$stateParams', '$timeout','$q',
function ($stateParams, $timeout, $q)
{
var deferred = $q.defer();
$timeout(function(){
deferred.resolve('MyLazyRevealedCtrl');
},250);
return deferred.promise;
}],
},
controllerProvider:['controllerName', function (controllerName)
{
return controllerName;
}],
我们可以看到的是只有一个计时器的简化示例(扮演异步 .then()
的角色)。它会等待一段时间,然后 return 解析控制器名称。
controllerProvider
然后(一旦全部解决)只需要结果,return将其作为字符串。
检查一下here