How to modify transcluded content before compile inside directive?

假装没事ソ 提交于 2019-12-12 08:35:05

问题


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.


回答1:


jcubic. You do not have to use $compile for what you are trying to do.

You can filter the transcluded element 'clone' and add css classes to the filtered nodes , but after that you have to append the modified clone to the template (it is identified by the 'element' attribute of the link function).

element.append(clone)

I created this jsfiddle for you.

If you still have other questions , please create a jsfiddle of your case.It Will be better to make an answer Thx




回答2:


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.




回答3:


If you're using angular > 1.3 and ngTransclude in template, so you need to update not the clone, but transcluded DOM, eg:

elm.find('ng-transclude')

http://jsfiddle.net/jhqkxgos/

but be sure to compile found elements if you update some you need to access from controller



来源:https://stackoverflow.com/questions/24575596/how-to-modify-transcluded-content-before-compile-inside-directive

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!