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!
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>
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
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);
})
}
}
})
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 .length
1
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.