我有一个抽象的父视图,用于与控制器的嵌套视图共享。
.state('edit', {
abstract: true,
url: '/home/edit/:id',
templateUrl: 'app/templates/editView.html',
controller: 'editController'
})
.state('edit.details', {
url: '/details',
templateUrl: 'app/templates/editDetailsView.html'
})
.state('edit.info', {
url: '/info',
templateUrl: 'app/templates/editInfoView.html'
})
路由按预期工作。
问题在于,当我从其中一个嵌套视图更新$scope
变量时,更改不会反映在视图中。当我从父视图中执行相同操作时,它可以正常工作。这不是需要$apply
的情况。
我的猜测是为每个视图创建了一个editController
的新实例,但我不确定为什么或如何修复它。
答案 0 :(得分:41)
这里的问题与此Q&答:How do I share $scope data between states in angularjs ui-router?。
如何解决它的方式隐藏在:
在AngularJS中,子范围通常原型继承自其父范围 ...
有一个'。'在你的模型中将确保原型继承发挥作用。
// So, use
<input type="text" ng-model="someObj.prop1">
// rather than
<input type="text" ng-model="prop1">.
还有这个
请记住,只有嵌套状态的视图时,范围属性才会继承状态链。范围属性的继承与状态的嵌套无关,也与视图嵌套(模板)无关。
完全有可能您有嵌套状态,其模板在您网站中的各种非嵌套位置填充ui-views。在这种情况下,您不能期望在子状态视图中访问父状态视图的范围变量。
我们应该在编辑Controller
中执行此操作controller('editController', function ($scope) {
$scope.Model = $scope.Model || {SomeProperty : "xxx"};
})
我们甚至可以重用controller: 'editController'
(我们不必这样做,因为$ scope.Model会在那里 - 感谢继承)
.state('edit', {
abstract: true,
url: '/home/edit/:id',
templateUrl: 'app/templates/editView.html',
controller: 'editController'
})
.state('edit.details', {
url: '/details',
templateUrl: 'app/templates/editDetailsView.html',
controller: 'editController'
})
.state('edit.info', {
url: '/info',
templateUrl: 'app/templates/editInfoView.html',
controller: 'editController'
})
现在,同一个控制器将被多次实例化(父所有孩子),但$scope.Model
只会启动一次(在父级内部)并且随处可用
答案 1 :(得分:14)
基于PilotBob
的评论当使用
controllerAs
模式给孩子说明自己的控制器时,是否可以这样做?
我决定使用controllerAs
追加另一个解决方案,同时保留above/original concept
状态现在将具有不同的控制器,父状态将其命名为“parentCtrl” (不会在具有子控制器的子范围中覆盖)
.state("main", {
controller:'mainController',
controllerAs: "parentCtrl",
...
.state("main.1", {
parent: 'main',
controller:'child1Controller',
controllerAs: "ctrl",
...
.state("main.2", {
parent: 'main',
controller:'child2Controller',
controllerAs: "ctrl",
...
这些是控制者:
.controller('mainController', function ($scope) {
this.Model = {Name : "yyy"};
})
.controller('child1Controller', function ($scope) {
$scope.Model = $scope.parentCtrl.Model;
})
.controller('child2Controller', function ($scope) {
$scope.Model = $scope.parentCtrl.Model;
})
检查行动here
答案 2 :(得分:1)
使用resolve
.state('edit', {
abstract: true,
url: '/home/edit/:id',
templateUrl: 'app/templates/editView.html',
controller: 'editController',
resolve: {
baseData: function() {
return {};
}
}
})
.state('edit.details', {
url: '/details',
templateUrl: 'app/templates/editDetailsView.html',
controller: 'editController'
})
.state('edit.info', {
url: '/info',
templateUrl: 'app/templates/editInfoView.html',
controller: 'editController'
})
.controller('editController', function (baseData) {
baseData.foo = baseData.foo || 'bar';
});
答案 3 :(得分:0)
在子控制器中,你可以这样做:
angular.extend($scope, $scope.$parent)
如果控制器与别名一起使用,例如'vm'你能做到:
let vm = angular.extend(this, $scope.$parent.vm);