在儿童指令之间共享数据

时间:2017-03-08 16:28:25

标签: javascript angularjs angularjs-directive angularjs-scope

我定义了三个指令:

  • 这应该在其他两个指令之间共享变量 - Child One和Child Two。

  • 儿童一

    这包含表示搜索词的输入字段。每当这个改变时,我使用链接函数来更新存储在父控制器中的变量。

    在现实世界中,我将根据这个术语进行搜索并更新阵列。但为了简单起见,我只想创建一个长度为1的新数组,我希望用搜索词来填充它的值。

  • 儿童二

    这应该显示结果数组。

由于某些原因,这不起作用,如果我将数组的长度设置为0并按下值,我将看到Child Two中的视图更新(我已经注释掉实现此目的的代码),但我想要理解为什么设置数组值不起作用。

我知道服务在这里是合适的,但是这个指令可能会在同一页面上多次重复使用,因此我不希望范围在页面上的每个项目之间发生冲突。

为什么视图不会使用我目前使用的代码进行更新?



var app = angular
  .module('SampleApplication', [])
  .directive('parent', function() {
    return {
      restrict: 'E',
      transclude: true,
      template: "<div ng-transclude></div>",
      controller: function($scope) {
        this.searchTerm = "";
        this.arrayContainingSearchTerm = [{value: ''}];
      
        this.updateSearchTerm = function(searchTerm) {
          this.searchTerm = searchTerm;
          
          //When this array is assigned - it doesn't get updated in the view
          this.arrayContainingSearchTerm = [{value: searchTerm}];
          
          //This will update the view.
          //this.arrayContainingSearchTerm.length = 0;
          //this.arrayContainingSearchTerm.push([{value: searchTerm}]);
        };
        
      }
    }
  })
  .directive('childOne', function() {
    return {
      restrict: 'E',
      require: '^^parent',
      template: "<div><h1>Child One</h1><input ng-model='searchTerm'></input></div>",
      link: function(scope, element, attrs, parentController) {
        scope.$watch('searchTerm', function(newValue, oldValue) {
          parentController.updateSearchTerm(newValue);
        });
      }
    }
  })
  .directive('childTwo', function() {
    return {
      restrict: 'E',
      require: '^^parent',
      template: "<div><h1>Child Two</h1><h2>Value below should be: {{searchTerm}}</h2><h2>{{arrayContainingSearchTerm}}</h2></div>",
      link: function(scope, element, attrs, parentController) {
        scope.searchTerm = parentController.searchTerm;
        scope.arrayContainingSearchTerm = parentController.arrayContainingSearchTerm;
      }
    }
  })
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>


<div ng-app="SampleApplication">
  <parent>
    <child-one></child-one>
    <child-two></child-two>
  </parent>
</div>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

你的第二条指令不知道你之后所做的改变 - 你需要$watch他们:

var app = angular
.module('SampleApplication', [])
.directive('parent', function() {
  return {
    restrict: 'E',
    transclude: true,
    template: "<div ng-transclude></div>",
    controller: function($scope) {
      this.searchTerm = "";
      this.arrayContainingSearchTerm = [{value: ''}];

      this.updateSearchTerm = function(searchTerm) {
        this.searchTerm = searchTerm;

        //When this array is assigned - it doesn't get updated in the view
        this.arrayContainingSearchTerm = [{value: searchTerm}];

        //This will update the view.
        //this.arrayContainingSearchTerm.length = 0;
        //this.arrayContainingSearchTerm.push([{value: searchTerm}]);
      };

    }
  }
})
.directive('childOne', function() {
  return {
    restrict: 'E',
    require: '^^parent',
    template: "<div><h1>Child One</h1><input ng-model='searchTerm'></input></div>",
    link: function(scope, element, attrs, parentController) {
      scope.$watch('searchTerm', function(newValue, oldValue) {
        parentController.updateSearchTerm(newValue);
      });
    }
  }
})
.directive('childTwo', function() {
  return {
    restrict: 'E',
    require: '^^parent',
    template: "<div><h1>Child Two</h1><h2>Value below should be: {{searchTerm}}</h2><h2>{{arrayContainingSearchTerm}}</h2></div>",
    link: function(scope, element, attrs, parentController) {
      scope.arrayContainingSearchTerm = parentController.arrayContainingSearchTerm;
      scope.searchTerm = parentController.searchTerm;
      scope.$watch(function() {
        scope.arrayContainingSearchTerm = parentController.arrayContainingSearchTerm;
      });

    }
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>


<div ng-app="SampleApplication">
  <parent>
    <child-one></child-one>
    <child-two></child-two>
  </parent>
</div>

答案 1 :(得分:1)

子范围自动继承父范围,并且可以使用$ parent /要求父控制器专门访问父范围,但请注意兄弟姐妹不能[轻松]访问其他范围。因此,解决方案是更新父作用域并将父作用域更改反映回目标子项。

您不需要更新子范围,因为子范围自动从父范围继承。而不是观察searchTerm ngModel,只需在childOne指令中使用attrs.ngModel。

var app = angular
.module('SampleApplication', [])
.directive('parent', function() {
  return {
    restrict: 'E',
    transclude: true,
    template: "<div ng-transclude></div>",
    controller: function($scope) {
      this.searchTerm = "";
      this.arrayContainingSearchTerm = [{value: ''}];

      this.updateSearchTerm = function(searchTerm) {
        this.searchTerm = searchTerm;

        //When this array is assigned - it doesn't get updated in the view
        this.arrayContainingSearchTerm = [{value: searchTerm}];

        //This will update the view.
        //this.arrayContainingSearchTerm.length = 0;
        //this.arrayContainingSearchTerm.push([{value: searchTerm}]);
      };

    }
  }
})
.directive('childOne', function() {
  return {
    restrict: 'E',
    require: '^^parent',
    template: "<div><h1>Child One</h1><input ng-model='searchTerm'></input></div>",
    link: function(scope, element, attrs, parentController) {
        // Just use attrs.ngModel
        parentController.updateSearchTerm(attrs.ngModel);
    }
  }
})
.directive('childTwo', function() {
  return {
    restrict: 'E',
    require: '^^parent',
    template: "<div><h1>Child Two</h1><h2>Value below should be: {{searchTerm}}</h2><h2>{{arrayContainingSearchTerm}}</h2></div>",
    link: function(scope, element, attrs, parentController) {
       // Comment/remove this since the scope is automatically inherit from parent scope
      //scope.arrayContainingSearchTerm = parentController.arrayContainingSearchTerm;
      //scope.searchTerm = parentController.searchTerm;
       // scope.arrayContainingSearchTerm = parentController.arrayContainingSearchTerm;

    }
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>


<div ng-app="SampleApplication">
  <parent>
    <child-one></child-one>
    <child-two></child-two>
  </parent>
</div>