Detect if a transclude content has been given for a angularjs directive

前端 未结 4 2138
小鲜肉
小鲜肉 2020-12-10 00:19

I have a directive (a progressbar) which should have two possible states, one without any description and one with a label on the left side. It would be cool to simple use

相关标签:
4条回答
  • 2020-12-10 00:51

    Based on the solution from @plong0 & @Ilan, this seems to work a bit better since it works with whitespace as well.

    $transcludeFn(function(clonedElement) {
        scope.hasTranscludedContent = clonedElement.html().trim() === "";
    });
    

    where previously <my-directive> </my-directive> would return that it has a .length of 1 since it contains a text node. since the function passed into $transcludeFn returns a jQuery object of the contents of the transcluded content, we can just get the inner text, remove whitespace on the ends, and check to see if it's blank or not.

    Note that this only checks for text, so including html elements without text will also be flagged as empty. Like this: <my-directive> <span> </span> </my-directive> - This worked for my needs though.

    0 讨论(0)
  • 2020-12-10 00:59

    Based on @Ilan's solution, you can use this simple $transclude function to know if there is transcluded content or not.

    $transclude(function(clone){
        if(clone.length){
            scope.hasTranscluded = true;
        }
    });
    

    Plnkr demonstrating this approach with ng-if to set default content if nothing to transclude: http://plnkr.co/hHr0aoSktqZYKoiFMzE6

    0 讨论(0)
  • 2020-12-10 01:02

    Here is a plunker: http://plnkr.co/edit/ednJwiceWD5vS0orewKW?p=preview

    You can find the transcluded element inside the linking function and check it's contents:

    Directive:

    app.directive('progressbar', function(){
      return {
        scope: {},
        transclude: true,
        templateUrl: "progressbar.html",
        link: function(scope,elm){
          var transcluded = elm.find('span').contents();
          scope.withLabel = transcluded.length > 0; // true or false
        }
      }
    })
    

    Template:

    <div class="progress" ng-class="{'with-label': withLabel}">
        <div class="label"><span ng-transclude></span>
        <div class="other">...</div>
    </div>
    

    You can also create your custom transclusion directive like so:

    app.directive('myTransclude', function(){
    
      return {
        link: function(scope, elm, attrs, ctrl, $transclude){
          $transclude(function(clone){
    
            // Do something with this:
            // if(clone.length > 0) ...
    
            elm.empty();
            elm.append(clone);
          })
        }
      }
    })
    
    0 讨论(0)
  • 2020-12-10 01:11

    After release of Angular v1.5 with multi-slot transclusion it's even simpler. For example you have used component instead of directive and don't have access to link or compile functions. Yet you have access to $transclude service. So you can check presence of content with 'official' method:

    app.component('myTransclude', {
      transclude: {
        'slot': '?transcludeSlot'
      },
      controller: function ($transclude) {
        this.transcludePresent = function() {
          return $transclude.isSlotFilled('slot');
        };
      }
    })
    

    with template like this:

    <div class="progress" ng-class="{'with-label': withLabel}">
        <div class="label"><span ng-transclude="slot"></span>
        <div class="other">...</div>
    </div>
    
    0 讨论(0)
提交回复
热议问题