I can pass a scope variable to a directive reference function, but not a compile function, angular

I am using ng-repeat and I need to pass the scope variable to the compile function of the directive. I know how to do this with reference, but not with compilation.

My html looks like this:

    <div ng-repeat="item in chapter.main">
      <block type="item.type"></block>
    </div>

      

Let's say item.type = "blah" regardless of the item. Then this link function works fine

app.directive('block', function() {
  return {
      restrict: 'E',
      link: function(scope, element, attributes){
            scope.$watch(attributes.type, function(value){
                console.log(value); //will output "blah" which is correct
            });

        }
  }
});

      

But I can't do the same with compilation?

app.directive('block', function() {
  return {
      restrict: 'E',
      compile: function(element, attrs, scope) {
        scope.$watch(attrs.type, function(value){
             console.log(value);
         });
      }
  }
});

      

The error I am getting is "cannot read the $ watch property of undefined" ..

This is how I would like my directive to look like this:

app.directive('block', function() {
  return {
      restrict: 'E',
      compile: function(element, attrs) {
        element.append('<div ng-include="\'{{type}}-template.html\'"></div>');
        //or element.append('<div ng-include="\'{' + attrs.type + '}-template.html\'"></div>');
        //except the above won't interpret attr.type as a variable, just as the literal string 'item.type'
      }
  }
});

      

+3


source to share


1 answer


The function compile

does not have scope

one of its parameters.

function compile(tElement, tAttrs, transclude) { ... }

NOTE: transclude has been deprecated in the latest version of Angular.

Is there any reason you don't want to use link

?

From DOC

The compilation function deals with transforming the DOM template. Since most directives do not perform template transformation, it is often not used. The compilation function takes the following arguments:

tElement - template element - the element in which the directive is declared. Safe template conversion for elements and children only.

tAttrs - template attributes - a normalized list of attributes declared in this element, split between all of the directive's compilation functions.

transclude - [DEPRECATED!] Transfer linking function: function (scope, cloneLinkingFn)

UPDATE



To access a scope from within a function compile

, you need to have a function preLink

or postLink

. In your case, you only need a function postLink

. So this ...

compile: function compile(tElement, tAttrs, transclude) {
    return function postLink(scope, element, attrs) { ... }
},

      

THE PROPOSED SOLUTION May not be exact, but should help you on your way.

Html

<div ng-app="myApp" ng-controller="app">
    <block type="item.type"></block>
</div>

      

JS (Controller + directive)

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

myApp.controller('app', function ($scope, $http) {
    $scope.item = {
        type: 'someTmpl'
    };
}).directive('block', ['$compile', function ($compile) {
    return {
        restrict: 'AE',
        transclude: true,
        scope: {
            type: '='
        },
        compile: function (element, attrs) {
            return function (scope, element, attrs) {
                var tmpl;
                tmpl = scope.type + '-template.html';

                console.log(tmpl);

                element.append('<div ng-include=' + tmpl + '></div>');

                $compile(element.contents())(scope);
            };
        }
    };
}]);

      

+2


source







All Articles