尽管被观看,角度ui-router中的命名视图仍未更新

时间:2014-08-21 04:45:14

标签: javascript angularjs angularjs-scope angularjs-ng-repeat angular-ui-router

我有一个范围变量$scope.foo,我正在监视。它可以通过表单中的文本字段进行更新。

我在使用angular ui-router渲染的页面上有两个命名视图AB。 命名视图A具有文本表单字段,通过ng-model="foo"监视控制器中的更改。当用户更改foo的值时,它会在正在$scope.bar指令中使用的控制器中更改另一个作用域变量ng-repeat的值,该变量是一个数组。命名视图B$scope.bar中的更改是使用控制器中的$scope.$watch方法进行的。

我面临的问题是foo发生更改的时间我可以看到bar在指定视图A上的更改,但 不是< / em> 在命名视图B上。

有人可以帮我解决这个问题吗?

修改Here是这个问题的佼佼者。

2 个答案:

答案 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)将此作为问题的示例传递给我。

首先有一个更新的工作version

那个plunker

,它可以满足我们的需要。主要变化有:

原始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]);
    }
  }

});

要提及的一些重要部分

予。最小公分母

我们必须将共享集合(数组栏)​​移动到父集合中。为什么?

  

我们必须将共享引用移动到最小公分母 - 到父范围

II。数组引用必须保持不变

我们必须保持对$scope.bar未更改的引用!这很重要。怎么实现呢?见:

在没有创建新引用的情况下,我们清除数组,保留对它的引用

// wrong
$scope.bar = [];
// good
$scope.bar.length = 0;

III。控制器可以有多个实例

此外,两个视图 A B 具有相同的控制器(实际上是相同的控制器名称)的事实,绝对不是,他们是同一个实例。

,他们是两个不同的实例......没有共享任何内容。这是我猜,最关键的混乱。见

  

控制器是特殊的,因为与服务不同,应用程序中可能有很多实例。例如,模板中的每个ng-controller指令都会有一个实例。

请注意updated example

中的所有内容