指令和控制器之间的通信,中间范围介于两者之间

时间:2013-09-20 18:56:14

标签: javascript angularjs angularjs-directive

我有以下AngularJS HTML代码:

<div ng-controller="myController">
    <div ng-grid="myGrid"></div>
</div>

ngGrid从视口,一系列行和这些行中的单元格中创建一个结构化的类似于表的组件。每个项目都有自己的范围。另外,我在其中一个单元格中创建了自己的指令,<range>指令类似于新的HTML5 <input type="number">标记。因此范围链看起来像这样:

myController -> ngGrid -> ngViewport -> ngRow -> ngCell -> range

我要做的是从<input>指令中获取<range>的值,并以可重复使用的方式将其传递给myController(换句话说,不是显式调用scope.$parent.$parent.$parent.$parent.$parent,以便我的指令可以在其他场景中重用。)

我试图按照this post的指示在指令代码中要求控制器,但无济于事。我也按照this egghead.io video的指示尝试了表达式绑定,但仍然没有成功。真的不知道如何从这里开始。

3 个答案:

答案 0 :(得分:0)

如果<input>是这样的(注意ng-model是第一级):

<input type="number" ng-model="value" />

更改模型,使其处于&gt;级别。 1:

<input type="number" ng-model="form.value" />

答案 1 :(得分:0)

他们能够使用父控制器的功能here的原因是因为他们也设置了“项目”项目&#39;模型等于父母的&#39;项目&#39;在指令的范围内。因此,为了能够在range指令中使用myController上的函数,您仍然需要在myController和范围之间的范围层之间设置相等的模型。

一种可能的解决方案是使用Angular的pubsub系统。如果在range指令中有一个特定的事件触发代码,它会让你知道你想在myController中捕获该值(例如onBlur事件),那么只需在范围层次结构中向上发出值,然后在myController中侦听该发出的事件捕捉价值。

从range指令发出事件并传递它的值

scope.$emit("CAPTURE_VALUE", scope.inputModel);

在myController中侦听事件,并捕获传递的值

$scope.$on("CAPTURE_VALUE", function(event, passedValue){
    $scope.rangeValue = passedValue;
};

现在只要range指令在myController的子范围内,无论它有多深,你都应该能够获得输入值。

答案 2 :(得分:0)

您不需要调用父链,您只需要范围。$ parent。由于范围原型继承自其父范围,因此可以安全地访问和修改任何非值类型的内容。查看this answer以获取有关范围继承如何工作的更多信息。

以下是您需要的所有代码。我以两种方式实现了通信示例;第一个使用公共模型的依赖注入,第二个引用父范围。

工作plunker

var app = angular.module('myApp', ['ngGrid']);

app.factory('rangeValues', function() {
    return [];
  });

app.controller('MyCtrl', function($scope, rangeValues) {
    $scope.factoryRangeValues = rangeValues;
    $scope.parentScopeRangeValues = [];
    $scope.myData = [{name: "Moroni", age: 50},
                     {name: "Tiancum", age: 43},
                         {name: "Jacob", age: 27},
                         {name: "Nephi", age: 29},
                         {name: "Enos", age: 34}];
    $scope.gridOptions = { 
        data: 'myData',
        columnDefs: [{field: 'name', displayName: 'Name'},
                     {field:'age', displayName:'Age', cellTemplate: '<div ng-class="{green: row.getProperty(col.field) > 30}"><div class="ngCellText"><div ng-range value="row.getProperty(col.field)">{{ value }}</div></div></div>'}]
        };
});

app.directive('ngRange', function(rangeValues) {
  return {
    restrict: 'EA',
    scope: {
      value: '='
    },
    link: function(scope, element, attrs) {
      // Pushing values to the injected model.
      rangeValues.push({
        value: scope.value
      });
      // Pushing values to the model on the parent scope
      scope.$parent.parentScopeRangeValues.push({
        value: scope.value
      })
    }
  }
});