Tim Coulter
Tim Coulter

Reputation: 8927

AngularJS: how to transclude and replace the containing element

I am trying to create a set of AngularJS directives that will conditionally render mutually exclusive segments of block or inline page content. For example, I envisage a mechanism that will render just the nth child element:

<selector member="index">
    <div>This div is visible when $scope.index equals 0</div>
    <div>This div is visible when $scope.index equals 1</div>
    <div>This div is visible when $scope.index equals 2</div>
</selector>

However, my design requires that the directives are implemented using custom element markup (not attributes applied to HTML elements) and that these HTML-invalid elements are removed from the DOM when rendering is complete. So, in the above example, a single matching div element would remain.

As a first attempt to prototype this concept, I converted the built in ngIf directive to use the following element-based syntax:

<if condition="true">
     <p>This is visible</p>
</if>

<if condition="false">
     <p>This is not visible</p>
</if>

Getting this to work simply entailed modifying restrict to E and changing the name of the watched attribute to condition. Here's my modified version of the built-in implementation:

application.directive("if", ['$animate', function ($animate) {
    return {
        transclude: 'element',
        priority: 1000,
        terminal: true,
        restrict: 'E',
        compile: function (element, attr, transclude) {
            return function ($scope, $element, $attr) {
                var childElement;
                var childScope;
                    $scope.$watch($attr.condition, function (value) {
                    if (childElement) {
                        $animate.leave(childElement);
                        childElement = undefined;
                    }

                    if (childScope) {
                        childScope.$destroy();
                        childScope = undefined;
                    }

                    if (toBoolean(value)) {
                        childScope = $scope.$new();
                        transclude(childScope, function (clone) {
                            childElement = clone;
                            $animate.enter(clone, $element.parent(), $element);
                        });
                    }
                });
            };
        }
    };
}]);

However, I'm not having much success eliminating the containing if element. I suspect I need a much better understanding of how transclusion is intended to work, but there doesn't seem to be much documentation around.

So, if you could either suggest the right technique to use, or point me in the direction of some relevant tutorials, I would really appreciate it.

Thanks, Tim

Upvotes: 4

Views: 6037

Answers (1)

iConnor
iConnor

Reputation: 20189

Isn't replace what you want?

    transclude: 'element',
    priority: 1000,
    terminal: true,
    restrict: 'E',
    replace: true, // ** //

That will replace the if with your content

Upvotes: 3

Related Questions