Обнаружить, было ли передаточное содержание предоставлено для директивы angularjs
У меня есть директива (progressbar), которая должна иметь два возможных состояния: одно без описания и одно с меткой слева.
Было бы здорово просто использовать переданный контент для этой метки.
Кто-нибудь знает, как я могу добавить класс в свою директиву, зависящий от того, было ли предоставлено трансключное содержимое или нет?
Итак, я хочу добавить:
<div class="progress" ng-class="{withLabel: *CODE GOES HERE*}">
<div class="label"><span ng-transclude></span>
<div class="other">...</div>
</div>
Спасибо большое!
Ответы
Ответ 1
После выпуска Angular v1.5 с переходом на несколько слотов он еще проще. Например, вы использовали component
вместо directive
и не имеете доступа к функциям link
или compile
. Тем не менее у вас есть доступ к сервису $transclude
. Таким образом, вы можете проверить наличие контента с помощью "официального" метода:
app.component('myTransclude', {
transclude: {
'slot': '?transcludeSlot'
},
controller: ($transclude) {
this.transcludePresent = function() {
return $transclude.isSlotFilled('slot');
};
}
})
с шаблоном, подобным этому:
<div class="progress" ng-class="{'with-label': withLabel}">
<div class="label"><span ng-transclude="slot"></span>
<div class="other">...</div>
</div>
Ответ 2
На основе решения @Ilan вы можете использовать эту простую функцию $transclude, чтобы узнать, есть ли переведенный контент или нет.
$transclude(function(clone){
if(clone.length){
scope.hasTranscluded = true;
}
});
Plnkr демонстрирует этот подход с помощью ng-if, чтобы установить содержимое по умолчанию, если ничего не перевести: http://plnkr.co/hHr0aoSktqZYKoiFMzE6
Ответ 3
Вот плункер: http://plnkr.co/edit/ednJwiceWD5vS0orewKW?p=preview
Вы можете найти переданный элемент внутри функции связывания и проверить его содержимое:
Директива
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
}
}
})
Шаблон:
<div class="progress" ng-class="{'with-label': withLabel}">
<div class="label"><span ng-transclude></span>
<div class="other">...</div>
</div>
Вы также можете создать свою настраиваемую директиву перехода:
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);
})
}
}
})
Ответ 4
Основываясь на решении от @plong0 и @Ilan, это, похоже, работает немного лучше, так как оно также работает с пробелами.
$transcludeFn(function(clonedElement) {
scope.hasTranscludedContent = clonedElement.html().trim() === "";
});
где ранее <my-directive> </my-directive>
возвращал бы то, что у него есть .length
of 1
, так как он содержит текст node. поскольку функция, переданная в $transcludeFn
, возвращает объект jQuery содержимого транскодированного содержимого, мы можем просто получить внутренний текст, удалить пробелы на концах и проверить, не пусто ли он или нет.
Обратите внимание, что это проверяет только текст, поэтому включение элементов html без текста также будет помечено как пустое. Например: <my-directive> <span> </span> </my-directive>
- Это работало для моих нужд.