Détecter si un contenu transclude a été donné pour une directive angularjs

j'ai une directive (une barre) qui doit avoir deux états possibles, une description et un avec une étiquette sur le côté gauche. Il serait cool d'utiliser simplement le contenu transclusif pour cette étiquette.

est-ce que quelqu'un sait comment je peux ajouter une classe à ma directive selon qu'un contenu transclude a été donné ou non?

Donc je veux ajouter:

<div class="progress" ng-class="{withLabel: *CODE GOES HERE*}">
    <div class="label"><span ng-transclude></span>
    <div class="other">...</div>
</div>

Merci beaucoup!

38
demandé sur Sebastian 2014-02-04 12:52:59

4 réponses

après la libération de V1 angulaire.5 avec la transclusion multi-slots, c'est encore plus simple. Par exemple, vous avez utilisé component au lieu de directive et n'ont pas accès à link ou compile fonctions. Pourtant, vous avez accès à $transclude service. Vous pouvez donc vérifier la présence de contenu avec la méthode "officielle":

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

avec le modèle comme ceci:

<div class="progress" ng-class="{'with-label': withLabel}">
    <div class="label"><span ng-transclude="slot"></span>
    <div class="other">...</div>
</div>
54
répondu Sergey Moiseev 2016-02-11 19:24:56

basé sur la solution de @Ilan, vous pouvez utiliser cette simple fonction $transclude pour savoir s'il y a du contenu transcluse ou non.

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

Plnkr la démonstration de cette approche avec ng-si pour définir le contenu par défaut si rien à transclude: http://plnkr.co/hHr0aoSktqZYKoiFMzE6

17
répondu plong0 2016-03-09 17:08:00

Voici un plunker: http://plnkr.co/edit/ednJwiceWD5vS0orewKW?p=preview

vous pouvez trouver l'élément transcluse à l'intérieur de la fonction de lien et vérifier son contenu:

la 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
    }
  }
})

Modèle:

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

vous pouvez aussi créer votre directive de transclusion personnalisée comme suit:

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);
      })
    }
  }
})
8
répondu Ilan Frumer 2014-02-04 09:31:14

basé sur la solution de @plong0 & @Ilan, cela semble fonctionner un peu mieux car il fonctionne avec whitespace aussi bien.

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

là où, auparavant,<my-directive> </my-directive> serait de retour qu'il a un .length1 puisqu'il contient un noeud de texte. puisque la fonction passée en $transcludeFn renvoie un objet jQuery du contenu du contenu transcluse, nous pouvons simplement obtenir le texte intérieur, supprimer les espaces sur les extrémités, et vérifier pour voir si c'est vide ou non.

Note que ce vérifie seulement pour le texte, donc y compris les éléments html sans texte seront aussi marqués comme vides. Comme ceci: <my-directive> <span> </span> </my-directive> - Cela a fonctionné pour mes besoins.

-1
répondu Chris Barr 2016-05-11 14:42:43