3
votes

I'm trying to build a "chart widget" directive with a clone button that will clone the chart and append it right after the original.

The directive looks like this:

app.directive("chartWidget", function ($compile) {
    return {
        restrict: "A", 
        transclude: true,
        templateUrl: 'chart-widget-template',
        link: function ($scope, element, attrs) {

            $scope.clone = function () {
                var clone = $compile("chart-widget-template")($scope);
                element.after(clone);
            };
        }
    };
});

With the template as follows:

 <script type="text/ng-template" id="chart-widget-template">
    <section class="widget chart-widget">
        <i ng-click="clone()" class="widget-clone-handle"></i>
        <div class="body no-margin">
            <div ng-transclude></div>
        </div>
    </section>
</script>

And usage as follows:

 <div data-chart-widget>
    <div data-some-specific-chart-directive></div>
 </div>

At first I tested the cloning to work without transclusion succesfully. However, once I add the transclusion in the mix, cloning it produces this error:

Error: [ngTransclude:orphan] Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element:

The angular docs for $compile state that the transcludeFn parameter to $compile is depracated (not that I know how it works anyways), so how would I accomplish this?

To clarify, I want the original transclusion aka:

<div data-some-specific-chart-directive></div>

to be included in each clone.

1

1 Answers

7
votes

Here is a demo plunker: http://plnkr.co/edit/ktEOsswQx3FyJ2pISqey?p=preview

You need to use the 5th argument of the linking function aka $transclude:

app.directive("chartWidget", function () {
    return {
        restrict: "A", 
        transclude: true,
        templateUrl: 'chart-widget-template',
        link: function ($scope, element, attrs, ctrl, $transclude) {
            $scope.clone = function () {
                $transclude(function(clone){
                  element.after(clone);  
                });
            };
        }
    };
});

The transclude function that is passed to the compile function is deperecated

See this commit: https://github.com/angular/angular.js/commit/90f87072e83234ae366cfeb3c281503c31dad738


Another plunker: http://plnkr.co/edit/0MJtWpXqLzOMuuA3DX0r?p=preview

  • use $templateCache.get to load the template
  • pass a transcludeFn as the second argument to $compile

Directive:

app.directive("chartWidget", function ($compile, $templateCache) {
    return {
        restrict: "A", 
        transclude: true,
        templateUrl: 'chart-widget-template',
        link: function (scope, element, attrs, ctrl, $transclude) {
            var template = $templateCache.get('chart-widget-template');
            scope.clone = function () {
                var clone = $compile(template,$transclude)(scope);
                element.after(clone);
            };
        }
    };
});