angular ui-router中的Named视图没有更新,尽管它被监视了
Named view in angular ui-router not updating, despite being watched
我有一个范围变量$scope.foo
,我一直在监视。它可以通过表单中的文本字段进行更新。
我有两个命名视图A
和B
在我使用角ui-router渲染的页面上。命名视图A
具有文本表单字段,通过ng-model="foo"
监视控制器中的更改。当foo
的值被用户改变时,它会改变控制器中另一个作用域变量$scope.bar
的值,这是一个数组,在命名视图B
上的ng-repeat
指令中使用。$scope.bar
中的更改是使用控制器中的$scope.$watch
方法进行的。
我面临的问题是,当foo
被改变时,我可以看到bar
在命名视图A
上的变化,但不是在命名视图B
上。
有人能帮我解决这个问题吗?
编辑:
有一个柱塞,这应该表明您的场景正在工作。
解决方案中最重要的部分是由:
- 仅通过视图层次继承(引用:)
请记住,只有当状态的视图嵌套时,作用域属性才会向下继承状态链。作用域属性的继承与状态的嵌套无关,而与视图(模板)的嵌套有关。
这是完全可能的,你有嵌套的状态,其模板填充ui-视图在各种非嵌套的位置在你的网站。在这种情况下,你不能期望在子状态视图中访问父状态视图的作用域变量。
让我再表达一次: 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)set from bar 2) $watch和3)set back to bar来跟随问题描述…但是如果数组包含对象,我们可以直接处理它们……没有这些开销,但那是另一个故事…
检查这里是如何工作的,并且视图A中的任何更改也在B中可见…因为继承了数组 bar
在parent $scope中声明的引用。
我创建了第二个答案,也遵循这个柱塞中的问题,@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]);
}
}
});
但是现在我们有两个(Parent和child):
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]);
}
}
});
需要提及的重要部分
。最小公分母
我们必须将共享集合(数组栏)移动到父元素中。为什么?
看我们必须将共享引用移动到最小公分母——父作用域
- 如何防止重新加载命名视图,当状态改变?AngularJS UI-Router
二世。对数组的引用必须保持不变
我们必须保持对父$scope.bar
的引用不变!这是必不可少的。如何做到这一点?看到:
- 替换数组内容的简写方法
不创建新的引用,而是清除数组,保留对它的引用
// wrong
$scope.bar = [];
// good
$scope.bar.length = 0;
III。控制器可以有多个实例
此外,两个视图A和B具有相同的控制器(实际上相同的控制器名称)这一事实绝对不意味着它们是相同的实例。
不,它们是两个不同的实例…不分享任何东西。我想这是最关键的困惑。看到
- angularjs指南-依赖注入
控制器是特殊的,与服务不同,在应用程序中可以有许多控制器的实例。例如,模板中每个ng-controller指令都有一个实例。
请注意,所有在更新后的示例
- 监视函数从服务返回不起作用,但作用域函数起作用
- Javascript循环不会自我更新
- 添加文字和评论功能更新Div
- AngularJS:ng之后,重复$scope值未按预期更新
- 如何通过数组更新角度子范围
- Ajax聊天消息重复而不仅仅是更新
- 通过CSV文件上载更新数据库表
- 平均值:无法将数据更新到数据库
- 在节点脚本中,如何监视文件的更改并获取更新的内容
- AngularJS:如何重新启动控制器以更新要监视的数据源模型
- 更新一个控制器中的模型,该模型被监视并位于不同的包中,并由另一个控制器使用
- 从指令更新作用域,并使用另一个指令进行监视
- 更新Angular Directive的值时出现问题's模型,同时从表单的监视进行更新
- angular ui-router中的Named视图没有更新,尽管它被监视了
- Angular.js在长轮询更改监视值时更新ng类
- Javascript中的循环/监视对象的更新
- Angular ng-repeat的最佳实践:只监视特定迭代中的更新
- 将作用域对象传递给可以监视和更新它的服务
- 监视嵌套在传递到角度组件的多个对象中的更新
- 监视不在$scope上的变量以更新在$scop上的变量