我有一个像这样开始的控制器(这个问题简化了):
angular.module('myApp.controllers')
.controller('MyController', ['$scope', '$routeParams', 'MyService',
function ($scope, $routeParams, MyService) {
MyService.fetchWithId($routeParams.id).then(function(model) {
$scope.model = model;
});
哪个好,但是在整个控制器的许多地方,我都有在视图中引用的参考模型的函数......
$scope.someFunctionMyViewNeeds = function() {
return $scope.model.someModelAttribute;
};
由于这些通常在获取完成之前运行,因此我最终会出现类似&#34的错误;无法读取未定义的属性"当视图试图看到someModelAttribute时。
到目前为止,我已尝试过三件事:
// before the fetch
$scope.model = new Model();
...但我真的不想要一个新模型,在某些情况下,如果没有其他依赖性,就无法完成初始化。
另一个想法是通过防御未使用的模型来丢弃代码,例如:
return ($scope.model)? $scope.model.someModelAttribute : undefined;
...但是,对于仅在获取完成时存在的条件,代码中有很多防御。
我的第三个想法是"解决"路由提供者中的模型,但我不知道如何做到这一点,并获得$ routeParams,其中保留了获取模型的参数。
我错过了一个更好的主意吗?
答案 0 :(得分:2)
如果您想使用resolve
,请尝试此操作。
var app = angular.module('app', ['ngRoute']);
app.config(function ($routeProvider) {
$routeProvider.when('/things/:id', {
controller: 'ThingsShowController',
resolve: {
model: function ($routeParams, MyService) {
return MyService.fetchWithId(+$routeParams.id);
}
},
template: '<a ng-href="#/things/{{model.id}}/edit">Edit</a>'
});
$routeProvider.when('/things/:id/edit', {
controller: 'ThingsEditController',
resolve: {
model: function ($routeParams, MyService) {
return MyService.fetchWithId(+$routeParams.id);
}
},
template: '<a ng-href="#/things/{{model.id}}">Cancel</a>'
});
});
// Just inject the resolved model into your controllers
app.controller('ThingsShowController', function ($scope, model) {
$scope.model = model;
});
app.controller('ThingsEditController', function ($scope, model) {
$scope.model = model;
});
// The rest is probably irrelevant
app.factory('Model', function () {
function Model(attributes) {
angular.extend(this, attributes);
}
return Model;
});
app.service('MyService', function ($q, Model) {
this.fetchWithId = function (id) {
var deferred = $q.defer();
deferred.resolve(new Model({ id: id }));
return deferred.promise;
};
});
// Just to default where we are
app.run(function ($location) {
$location.path('/things/123');
});
app.run(function ($rootScope, $location) {
$rootScope.$location = $location;
});
// Because $routeParams does not work inside the SO iframe
app.service('$routeParams', function () {this.id = 123;});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.9/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.9/angular-route.min.js"></script>
<div ng-app="app">
<div>Route: {{$location.path()}}</div>
<div ng-view=""></div>
</div>
&#13;