Search code examples
angularjsangular-directiveangularjs-ng-transclude

Manual transclude in link with ng-repeat


I have an angular application which uses an ng-repeat-start to display some dynamic information.

<div>
  <table>
    <tbody>
      <tr my-directive ng-repeat="data in vm.data">
        <td ng-bind="data.id"></td>    
        <td ng-bind="data.id"></td>    
      </tr>
        <tr ng-repeat-end>
        <td>extrarow</td>
      </tr>
    </tbody>
  </table>
</div>

I also built a directive which I want to use to apply a class to the whole tr depending on the value of some of the data. I wanted to use link to do that instead of using a $watch.

As the itself can contain many inside, I wanted to use transclude to do this. I don´t want the tag to be inserted in my table as this breaks all my styles, so I have to do this manually, something like this:

function myDirective() {
    return {
       transclude: true,
       scope: {},
       link: function($scope, $element, $attrs, $ctrl, $transclude) {
          var cloned = $transclude();
          $element.append(cloned);              
       }
    }
}

The problem is this is not working as expected. The cloned object is only being appended to the last row of the ng-repeat. It's probably due to the $element object, but I'm not sure about it.

I reproduced the problem in this jsfiddle.

Any ideas on where the problem is? Many thanks.


Solution

  • I am befuddled why you're requiring transclude. I think this is what you're looking for; however I have to say I am not convinced about the economy of $observe over $watch here.

    For $observe, I've added the following to the TR:

     <tr my-directive data-value="{{data.id}}" ng-repeat="data in vm.data"> 
    

    and the directive demonstrates the class change on some condition.

    function myDirective() {
          return {
            link: function($scope, element, attrs) {
              attrs.$observe('value', function(val) {
                if (val && val == "9.2")
                  element.addClass("myClass");
                else
                  element.removeClass("myClass");
              });              
           }
        }
      }