Passing the attribute of the parent directive to the attribute of the child directive

I create directives for a library that clients can use. I need clients to create their own templates for the directive and pass the absolute value of the URL of this template to my directives. One of my directives will have another custom directive within it, and the template will be calculated based on the value of one of the attributes of the parent directive. Here is an example:

<parent-dir menu-template="this.html" item-template="that.html"></parent-dir> 

I have a template for this directive that looks like this:

 <ul style="list: none" ng-repeat="item in menu"> <child-dir template="{{itemTemplate}}"></child-dir> </ul> 

My directives are as follows:

 angular.module('myApp') .directive('parentDir', function () { return { restrict: 'E', scope: { menuTemplate: '@', itemTemplate: '@', menuType: '@', menuName: '@', menuId: '@', }, templateUrl: function (element, attrs) { alert('Scope: ' + attrs.menuTemplate); return attrs.menuTemplate; }, controller: function ($scope, $element, $attrs) { $scope.defaultSubmit = false; alert('Menu: '+$attrs.menuTemplate); alert('Item: ' + $attrs.itemTemplate); $scope.itemTemplate = $attrs.itemTemplate; if ($attrs.$attr.hasOwnProperty('defaultSubmit')) { alert('It does'); $scope.defaultSubmit = true; } } }; }) .directive('childDir', function () { return { restrict: 'E', require: '^parentDir', templateUrl: function (element, attrs) { alert('Item Template: ' + attrs.template); return attrs.template; }, controller: function ($scope, $element, $attrs) { $scope.job; alert('Under job: ' + $scope.itemTemplate); } }; }); 

I do not show all the code, but this is the main part of my problem. When I run this, I keep getting undefined for the template on childDir.

What is the best practice to perpetuate the itemTemplate value from parentDir so that childDir can use it as a template?

+5
source share
1 answer

The reason you run into problems is because the function that generates templateUrl is executed before the scope been assigned to your directive - something that needs to be done before the interpolated data can be replaced.

In other words: at the point where the templateUrl function is executed, the value of the template attribute is still "{{itemTemplate}}" . This will remain in effect until a directory link ( preLink ) is launched.

I created a plunker to demonstrate the point here . Do not forget to open the console. You will see that templateUrl is executed before both the parent and child link functions.

So what are you doing instead?

Fortunately, angular provides the $templateRequest service, which allows you to request a template in the same way as when using templateUrl (it also uses $templateCache , which is convenient).

put this code in your link:

  $templateRequest(attrs.template) .then(function (tplString){ // compile the template then link the result with the scope. contents = $compile(tplString)(scope); // Insert the compiled, linked element into the DOM elem.append(contents); }) 

You can then remove any template reference in the directive definition object, and this will safely be done after the attribute has been interpolated.

+4
source

All Articles