Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify transcluded content before compile inside directive?

What I want to do, is to handle transclude by hand and modify the content before I insert into the DOM:

return {
    restrict: 'E',
    transclude: true,
    template: '<HTML>',
    replace: true,
    link: function(scope, element, attrs, ngModelCtrl, $transclude) {

        var caption = element.find('.caption');

        $transclude(function(clone) {
            console.log(clone);
            clone.filter('li').addClass('ng-hide'); // this don't work
            clone.addClass('ng-hide'); // same this one
            clone.attr('ng-hide', 'true'); // same this one
            $compile(clone)(scope.$new()).appendTo(caption);
            caption.find('li').addClass('ng-hide'); // and this
        });
    }
}

In angular.js source I found this example:

  var templateElement = angular.element('<p>{{total}}</p>'),
      scope = ....;

  var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {
    //attach the clone to DOM document at the right place
  });

  //now we have reference to the cloned DOM via `clonedElement`

but when I add clonedElement.appendTo(caption); inside link function it only add comment with ng-repeat inside.

I need this because I need to hide all elements in this case

<dropdown>
  <li ng-repeat="item in items"><a>{{item.label}}</a></li>
</dropdown>

I need to modify the template before compile or DOM after ng-repeat is expanded. Before would be better because I will be able to add logic using ng-hide directive instead of ng-hide class.

like image 286
jcubic Avatar asked Jul 04 '14 13:07

jcubic


1 Answers

I realise it's been a long time since this question was posted, but I hope you may find the following useful.

I've been quite long and heavily in this (transclusion) business, I tried a few ways to achieve what you @jcubic need and finally I came across a solution which is really robust and quite simple.

...
replace: false,
transclude: false,
compile: function( tElement, tAttributes ) {

    // store your "transcluded" content of the directive in the variable
    var htmlContent = tElement.html();
    // then remove it
    tElement.html('');

    return function postLink(scope, elem, attrs) {
        // then html var is available in your link! 
        var $html = $('<div />',{ html:htmlContent }); // for much easier manipulation (so you can use DOM functions - you can also manipulate directly on htmlContent string)

        // so you can manipulate the content however you want
        scope.myVariable = true;
        $html.find('li').attr('ng-hide', 'myVariable'); // add native directive
        $html.removeClass('inner-content').addClass('my-inner-content'); // add/remove class
        $html.find('#myElement').attr('my-directive',''); // add custom directive etc. etc.

        // after you finished you just need to compile your html and append your directive element - also however you want
        // you also convert back $html to the string
        elem.append( $compile( $html.html() )(scope) ); // append at the end of element
        /* or: 
        elem.find('.my-insert-point').html( $compile( $html.html() )(scope) ); // append the directive in the specific point
        elem.find('[my-transclude]').html( $compile( $html.html() )($parent.scope) ); // once the scope:true it will be the same as native transclusion ;-) 
        scope.variable = $html.html(); // or you can probably assign to variable and use in your template with bind-html-compile (https://github.com/incuna/angular-bind-html-compile) - may need $sce.trustAsHtml
        */
     }
}
...

So as you can see you have full control on your "transcluded" content and you don't even need transclusion! :-)

ps. I tested it with Angular 1.4. Not sure if it works with replace:true (I wasn's bother to test it as it's minor nuisance if it doesn't). You can use pre and post link as normally you'd use within compile function and you need to inject $compile service into your directive.

like image 179
Karol Websky Avatar answered Nov 02 '22 11:11

Karol Websky