2

I've got the following AngularJS HTML code:

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

ngGrid creates a structured table-like component out of a viewport, a series of rows, and cells within those rows. Each of those items has their own scope. In addition, I created my own directive in one of those cells, a <range> directive similar to the new HTML5 <input type="number"> tag. So the scope chain looks like this:

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

what I'm trying to do is grab the <input>'s value from within the <range> directive and pass that along to myController in a reusable way (in other words, NOT explicitly calling scope.$parent.$parent.$parent.$parent.$parent so my directive can be reused in other scenarios).

I tried requiring the controller within the directive code as directed by this post but to no avail. I've also tried expression binding as directed by this egghead.io video and still no success. Really not sure how to proceed from here.

Community
  • 1
  • 1
acconrad
  • 3,201
  • 1
  • 22
  • 31

3 Answers3

0

If the <input> is like this (note ng-model is first level):

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

Change the model so that it is in a level > 1:

<input type="number" ng-model="form.value" />
Nikos Paraskevopoulos
  • 39,514
  • 12
  • 85
  • 90
0

The reason they are able to utilize the parent controller's function here is because they are also setting 'item' model equal to the parent's 'item' in the scope of the directive. So for you to be able to use a function on myController in your range directive, you still need to have a model set equal between ever scope layer between myController and range.

One possible solution for you would be to use Angular's pubsub system. If there is a specific event firing code in the range directive that would let you know you want to capture that value in myController (for example onBlur event), then simply emit the value up the scope hierarchy, and listen for that emitted event in myController to capture the value.

emit event from range directive and pass it's value

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

listen for event in myController, and capture the value passed

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

now as long as the range directive is in a child scope of myController you should be able to get the input value no matter how deep it is.

mikeStone
  • 190
  • 1
  • 6
0

You don't need to call the parent chain, all you need is scope.$parent. Because scopes prototypically inherit from their parent scope, anything that isn't a value type can be accessed and modified safely. Check out this answer for more on how scope inheritance works.

Here is all the code you need. I implemented the communication example in two ways; the first uses dependency injection of a common model, and the second references the parent scope.

Working 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
      })
    }
  }
});
Community
  • 1
  • 1
mortalapeman
  • 1,415
  • 12
  • 16