Подтвердить что ты не робот

Обнаружить, было ли передаточное содержание предоставлено для директивы angularjs

У меня есть директива (progressbar), которая должна иметь два возможных состояния: одно без описания и одно с меткой слева. Было бы здорово просто использовать переданный контент для этой метки.

Кто-нибудь знает, как я могу добавить класс в свою директиву, зависящий от того, было ли предоставлено трансключное содержимое или нет?

Итак, я хочу добавить:

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

Спасибо большое!

4b9b3361

Ответ 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> - Это работало для моих нужд.