AngularJS: how to transclude and replace the containing element

6k views Asked by At

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

1

There are 1 answers

3
iConnor On

Isn't replace what you want?

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

That will replace the if with your content