title: AngularJS: how to transclude and replace the containing element
body: <p>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:</p>
  
  <pre><code>&lt;selector member="index"&gt;
      &lt;div&gt;This div is visible when $scope.index equals 0&lt;/div&gt;
      &lt;div&gt;This div is visible when $scope.index equals 1&lt;/div&gt;
      &lt;div&gt;This div is visible when $scope.index equals 2&lt;/div&gt;
  &lt;/selector&gt;
  </code></pre>
  
  <p>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 <code>div</code> element would remain.</p>
  
  <p>As a first attempt to prototype this concept, I converted the built in <code>ngIf</code> directive to use the following element-based syntax:</p>
  
  <pre><code>&lt;if condition="true"&gt;
       &lt;p&gt;This is visible&lt;/p&gt;
  &lt;/if&gt;
  
  &lt;if condition="false"&gt;
       &lt;p&gt;This is not visible&lt;/p&gt;
  &lt;/if&gt;
  </code></pre>
  
  <p>Getting this to work simply entailed modifying <code>restrict</code> to <code>E</code> and changing the name of the watched attribute to <code>condition</code>. Here's my modified version of the built-in implementation:</p>
  
  <pre><code>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);
                          });
                      }
                  });
              };
          }
      };
  }]);
  </code></pre>
  
  <p>However, I'm not having much success eliminating the containing <code>if</code> 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.</p>
  
  <p>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.</p>
  
  <p>Thanks,
  Tim</p>