Search code examples
javascriptangularjsangularjs-directiveangularjs-scope

Angular isolated scope values not visible in template when using replace


I am creating a small app and I have the following directive with the template.

smallgrid.directive.js:

angular.module('myActions')
    .directive('smallgrid', ['$rootScope', function($rootScope) {
        return {
            restrict: "E",
            scope: {
                actionable: "="
            },
            controller: function($scope) {
                $scope.setLocation = function() {
                    console.log("yee");
                };
            }
        };
    }])
    .directive('three', function() {
        return {
            replace: true,
            templateUrl: '/app/my_actions/directives/templates/grid3x3.template.html'
        };
    })
    .directive('four', function() {
        return {
            replace: true,
            templateUrl: '/app/my_actions/directives/templates/grid4x4.template.html'
        };
    })
    .directive('five', function() {
        return {
            replace: true,
            templateUrl: '/app/my_actions/directives/templates/grid5x5.template.html'
        };
    });

grid3x3.template.html

<div class="k-edit-field" id="board">
    <div class="row" ng-click="setLocation()">
        {{actionable.probability}}
    </div>
</div>

I use this directive as follows:

<smallgrid three actionable="currentAction.actionable" ng-if="somecondition"></smallgrid>

The UI renders properly. However it shows {{actionable.probability}} is empty and the Click event is not firing. However, if I remove the isolated scope and access the variable directly, values are available. I understand that when I am using isolated scopes, in the three directive, I can't access values of smallgrid. Is there a way to pass those values from smallgrid to the template?


Solution

  • Passing a directive as an attribute of a directive you're bound to have scope problems.

    It will look better if you use scope inheritance for nested directives with ng-transclude.

    So your starting point should be

    <smallgrid actionable="currentAction.actionable" ng-if="somecondition">
      <three></three>
    </smallgrid>
    

    This way <three> has access to the $parent

    function smallgrid() {
      return {
        restrict: "E",
        transclude: true,
        scope: {
          actionable: "="
        },
        template: `<div ng-transclude></div>`,
        controller: function($scope) {
          $scope.setLocation = function() {
            console.log("yee");
          };
        }
      };
    }
    function three() {
      return {
        template: `<div class="k-edit-field" id="board">
                    <div class="row" ng-click="$parent.setLocation()">
                      test = {{$parent.actionable.probability}}
                    </div>
                  </div>`
      };
    }
    function myController($scope) {
      $scope.currentAction = {actionable: {probability: "test"}};
      $scope.somecondition = true;
    }
    angular.module('myApp', []);
    angular
        .module('myApp')
        .controller('myController', myController)
        .directive('smallgrid', smallgrid)
        .directive('three', three);
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
    <div ng-app="myApp">
      <div ng-controller="myController">
        <smallgrid actionable="currentAction.actionable" ng-if="somecondition">
          <three></three>
        </smallgrid>
      </div>
    </div>