UI-Router
与Angular
的{{1}}不同。它支持普通ngRoute
可以执行的所有操作以及许多额外功能。
我正在将ngRoute
应用从Angular
更改为ngRoute
。但我无法弄清楚如何以编程方式注入UI-Router
函数 - 我在resolve
和Controller
之外使用的一段代码。
因此,使用标准config
的{{1}}我可以在Angular
运行块中动态注入ngRoute
:
resolve promise
现在如何使用Angular
以类似的方式注入解决方案承诺?我尝试通过app.run(function ($route) {
var route = $route.routes['/'];
route.resolve = route.resolve || {};
route.resolve.getData = function(myService){return myService.getSomeData();};
});
来访问UI-Router
,但这对我来说失败了。
$stateProvider
答案 0 :(得分:6)
您可以使用resolve
在控制器加载下一个状态之前为其提供数据。要访问已解析的对象,您需要将它们作为依赖项注入控制器。
我们以购物清单应用程序为例。我们首先定义我们的应用程序模块,并将ui.router
作为依赖项。:
angular.module('myApp', ['ui.router']);
我们现在想要定义特定于我们应用程序的购物清单页面的模块。我们将定义一个shoppingList
模块,包括该模块的状态,该状态的解析以及控制器。
购物清单模块
angular.module('myApp.shoppingList').config(function ($stateProvider) {
$stateProvider.state('app.shoppingList', {
url: '/shopping-list',
templateUrl: 'shopping-list.html',
controller: 'ShoppingListController',
resolve: {
shoppingLists: function (ShoppingListService) {
return ShoppingListService.getAll();
}
}
});
});
我们现在可以将已解析的对象作为依赖项注入控制器。在上面的状态中,我正在解析一个名为shoppingLists
的对象。如果我想在我的控制器中使用这个对象,我将它包含为具有相同名称的依赖项。
购物清单控制器
angular.module('myApp.shoppingList').controller('ShoppingListController', function ($scope, shoppingLists) {
$scope.shoppingLists = shoppingLists;
});
有关其他详细信息,请阅读Angular-UI Wiki,其中包含in-depth guide to using resolve。
答案 1 :(得分:0)
查看文档:
您可以使用resolve为控制器提供自定义状态的内容或数据。 resolve是一个可选的依赖关系图,应该注入控制器。
如果这些依赖项中的任何一个是promise,它们将在实例化控制器并触发$ stateChangeSuccess事件之前被解析并转换为值。
resolve属性是一个地图对象。 map对象包含键/值对:
- key - {string}:要注入控制器的依赖项的名称。
- factory - {string | function}:
- 如果是字符串,则它是服务的别名。
- 否则,如果是函数,则将其注入,并将返回值视为依赖项。如果结果是承诺,则解决 在实例化控制器并将其值注入之前 控制器。
示例:
在实例化控制器之前,必须解析下面解决的每个对象(如果它们是承诺,则通过deferred.resolve())。注意每个解析对象如何作为参数注入控制器。
州的示例代码
$stateProvider.state('myState', {
resolve:{
// Example using function with simple return value.
// Since it's not a promise, it resolves immediately.
simpleObj: function(){
return {value: 'simple!'};
},
// Example using function with returned promise.
// This is the typical use case of resolve.
// You need to inject any services that you are
// using, e.g. $http in this example
promiseObj: function($http){
// $http returns a promise for the url data
return $http({method: 'GET', url: '/someUrl'});
},
// Another promise example. If you need to do some
// processing of the result, use .then, and your
// promise is chained in for free. This is another
// typical use case of resolve.
promiseObj2: function($http){
return $http({method: 'GET', url: '/someUrl'})
.then (function (data) {
return doSomeStuffFirst(data);
});
},
// Example using a service by name as string.
// This would look for a 'translations' service
// within the module and return it.
// Note: The service could return a promise and
// it would work just like the example above
translations: "translations",
// Example showing injection of service into
// resolve function. Service then returns a
// promise. Tip: Inject $stateParams to get
// access to url parameters.
translations2: function(translations, $stateParams){
// Assume that getLang is a service method
// that uses $http to fetch some translations.
// Also assume our url was "/:lang/home".
return translations.getLang($stateParams.lang);
},
// Example showing returning of custom made promise
greeting: function($q, $timeout){
var deferred = $q.defer();
$timeout(function() {
deferred.resolve('Hello!');
}, 1000);
return deferred.promise;
}
},
示例控制器,使用上述
resolve
内容
// The controller waits for every one of the above items to be
// completely resolved before instantiation. For example, the
// controller will not instantiate until promiseObj's promise has
// been resolved. Then those objects are injected into the controller
// and available for use.
controller: function($scope, simpleObj, promiseObj, promiseObj2, translations, translations2, greeting){
$scope.simple = simpleObj.value;
// You can be sure that promiseObj is ready to use!
$scope.items = promiseObj.data.items;
$scope.items = promiseObj2.items;
$scope.title = translations.getLang("english").title;
$scope.title = translations2.title;
$scope.greeting = greeting;
}
})
答案 2 :(得分:0)
您无法访问$stateProvider
中的run
,我认为您在创建状态配置后不应该更改状态配置(并且您可能无法做到无论如何),为什么不在状态创建上添加resolve?
答案 3 :(得分:0)
为了无条件地将resolve
添加到一个或多个状态,应该使用抽象状态进行继承:
$stateProvider
.state('root', {
abstract: true,
resolve: {
common: ...
},
})
.state('some', {
parent: 'root',
...
});
这是首选的方法,不需要黑客攻击。
至于UI路由器中等效的动态$route
解析器,这是一个小问题。使用state
方法注册状态时,它将在内部存储prototypically inherited from the definition,而不是仅仅分配给状态存储。
虽然稍后可以使用$state.get('stateName')
获取定义,但它与路由器内部使用的对象不同。由于JS继承的工作原理,如果状态中存在resolve
对象,它将没有区别,因此可以在那里添加新的解析器属性。但如果没有$state.get('stateName').resolve
,那就是死路一条。
解决方案是修补state
方法并将resolve
对象添加到所有状态,因此可以在以后修改解析器集。
angular.module('ui.router.hacked', ['ui.router'])
.config(function ($stateProvider) {
var stateOriginal = $stateProvider.state;
$stateProvider.state = function (name, config) {
config.resolve = config.resolve || {};
return stateOriginal.apply(this, arguments);
}
})
angular.module('app', ['ui.router.hacked']).run(function ($state) {
var state = $state.get('some');
state.resolve.someResolver = ...;
});
与任何其他黑客一样,它可能有陷阱并且往往会破裂。虽然这个非常坚固和简单,但它需要额外的单元测试,如果可以使用传统方法,则不应该使用它。