Как запросить вложенный элемент DOM директивы Angularjs с помощью динамического селектора?

Распределение директив внутри родительского шаблона:

<div badge></div>

Директивный шаблон templates/badge.html:
Обратите внимание на распределение динамического идентификатора, используя директиву $id ,

<div>
    <span id="id{{ ::$id }}_name">Nik Sumeiko, Frontend engineer</span>
</div>

Директива:

angular.module('app').directive('badge', () => ({
  restrict: "A",
  replace: true,
  templateUrl: "templates/badge.html",
  link: (scope, element, attributes) => {

    // Tries to query nested DOM element by a dynamic selector.
    const name = element.find(`#id${scope.$id}_name`);

    console.log(name.length, element.html());
  }
}));

По выводу консоли ясно видно, что шаблон директивы еще не скомпилировал свои динамические значения:

0 "
    <div>
      <span id="id{{ ::$id }}_name">Nik Sumeiko, Frontend engineer</span>
    </div>
"

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

Пожалуйста, не предлагайте использовать $timeout встроенная функция для задержки рендеринга шаблона внутри link метод, так как я не думаю, что это правильный путь...

1 ответ

Вот цитата из угловой документации:

После связывания представление не обновляется до тех пор, пока не будет вызван вызов $digest, который обычно выполняется Angular автоматически.

Вот почему вы не можете найти элементы, содержащие выражения в их идентификаторе - в это время представление не обновляется.

Вот обходные пути:

Создайте элемент и присоедините его к DOM вручную

Таким образом, у вас есть ссылка на элемент, поэтому вам не нужно запрашивать его:

link: (scope, element, attributes) => {
    let span = $compile('<span id="id{{ ::$id }}_name">Nik Sumeiko, Frontend engineer</span>')(scope);
    // do something to span ...
    element.append(span);
}

Используйте $ timeout

Ты можешь использовать $timeout с нулевой задержкой, это не неправильный путь. $timeout выполнит ваш код сразу после текущего $digest цикл, то есть после обновления привязок вида:

link: (scope, element, attributes) => {
    $timeout(function() {
        let span = element[0].querySelector(`#id${scope.$id}_name`);
    });
}