我有一个范围变量$scope.foo
,我正在监视。它可以通过表单中的文本字段进行更新。
我在使用angular ui-router渲染的页面上有两个命名视图A
和B
。
命名视图A
具有文本表单字段,通过ng-model="foo"
监视控制器中的更改。当用户更改foo
的值时,它会在正在$scope.bar
指令中使用的控制器中更改另一个作用域变量ng-repeat
的值,该变量是一个数组。命名视图B
。 $scope.bar
中的更改是使用控制器中的$scope.$watch
方法进行的。
我面临的问题是foo
发生更改的时间我可以看到bar
在指定视图A
上的更改,但 不是< / em> 在命名视图B
上。
有人可以帮我解决这个问题吗?
修改: Here是这个问题的佼佼者。
答案 0 :(得分:5)
有plunker,表明您的方案正在运行。
该解决方案最重要的部分是:
请记住,如果状态的视图嵌套,范围属性只会继承状态链。 范围属性的继承与状态的嵌套无关以及与视图(模板)的嵌套有关的所有内容。
完全有可能您有嵌套状态,其模板在您网站中的各种非嵌套位置填充ui-views。 在这种情况下,您不能指望在子状态视图中访问父状态视图的范围变量。
让我再次表达一下: scope
继承仅通过view
嵌套进行。
我们可以创建这种状态定义:
$stateProvider
.state('root', {
url: '/root',
templateUrl: 'tpl.root.html',
controller: 'RootCtrl', // this root scope will be parent
})
.state('root.entity', {
url: '/entity',
views:{
'A': {
templateUrl: 'tpl.a.html',
controller: 'ACtrl', // scope is inherited from Root
},
'B': {
templateUrl: 'tpl.b.html',
controller: 'ACtrl', // scope is inherited from Root
}
}
})
因此状态定义支持嵌套视图 - 让我们从中获利并将 $scope.bar
集合放入父级。然后,所涉及的所有视图都可以访问相同的集合:
.controller('RootCtrl', function ($scope, $state) {
$scope.bar = ['first', 'second', 'last'];
})
.controller('ACtrl', function ($scope, $state) {
// *) note below
$scope.foo = $scope.bar[0];
$scope.$watch("foo", function(val){$scope.bar[0] = val; });
})
.controller('BCtrl', function ($scope, $state) {
})
*)注意:这里我们做1)设置吧2)$ watch和3)设置回bar以跟随问题描述...但是如果数组包含对象,我们可以直接使用它们。没有那个开销,但这是另一个故事...
检查here如何运作,以及 A 中的任何更改在 B 中都可见...因为继承了对数组的引用<在父$ scope中声明的strong> bar
。
答案 1 :(得分:3)
我创建了第二个答案以跟随此plunker中的问题,@skip(OP)将此作为问题的示例传递给我。
,它可以满足我们的需要。主要变化有:
原始state
def:
.state('home', {
url: '/',
views: {
'': { templateUrl: 'home.html' },
'A@home': {
templateUrl: 'a.html',
controller: 'MainCtrl'
},
'B@home': {
templateUrl: 'b.html',
controller: 'MainCtrl'
}
}
替换为 RootCtrl
定义:
.state('home', {
url: '/',
views: {
'': {
templateUrl: 'home.html',
controller: 'RootCtrl' // here we do use parent scoping
},
'A@home': {
templateUrl: 'a.html',
controller: 'MainCtrl'
},
'B@home': {
templateUrl: 'b.html',
controller: 'MainCtrl'
}
}
这是一个控制器:
app.controller('MainCtrl', function($scope) {
var fruits = [{"name": "Apple"}, {"name": "Banana"}, {"name": "Carrot"}];
$scope.bar = $scope.bar || [];
$scope.foo = 2;
$scope.$watch('foo',function(value, oldValue){
$scope.bar = [];
getBar(fruits, value);
});
function getBar(fruits, howManyFruits) {
for(var i=0; i < $scope.foo; i++) {
$scope.bar.push(fruits[i]);
}
}
});
但现在我们有两个(父母和孩子):
app.controller('RootCtrl', function($scope) {
$scope.bar = [];
})
app.controller('MainCtrl', function($scope) {
var fruits = [{"name": "Apple"}, {"name": "Banana"}, {"name": "Carrot"}];
//$scope.bar = $scope.bar || [];
$scope.foo = 2;
$scope.$watch('foo',function(value, oldValue){
$scope.bar.length = 0;
getBar(fruits, value);
});
function getBar(fruits, howManyFruits) {
for(var i=0; i < $scope.foo; i++) {
$scope.bar.push(fruits[i]);
}
}
});
我们必须将共享集合(数组栏)移动到父集合中。为什么?
我们必须将共享引用移动到最小公分母 - 到父范围
见
我们必须保持对父$scope.bar
未更改的引用!这很重要。怎么实现呢?见:
在没有创建新引用的情况下,我们清除数组,保留对它的引用
// wrong
$scope.bar = [];
// good
$scope.bar.length = 0;
此外,两个视图 A 和 B 具有相同的控制器(实际上是相同的控制器名称)的事实,绝对不是,他们是同一个实例。
否,他们是两个不同的实例......没有共享任何内容。这是我猜,最关键的混乱。见
中的所有内容控制器是特殊的,因为与服务不同,应用程序中可能有很多实例。例如,模板中的每个ng-controller指令都会有一个实例。