Как подождать до конца $compile в angularJS

Я загружаю шаблон и компилирую его в свою область с помощью службы $compile.

var template = "<div> .. {{someCompilingStuff}} ..</div>";
var compiled = $compile(template)(cellScope);

а затем используя его в popover

cellElement.popover({
    html: true,
    placement: "bottom",
    trigger: "manual",
    content: compiled
});

Мой шаблон довольно сложный и может потребоваться некоторое время для компиляции.

Как я могу убедиться, что angular закончил компиляцию шаблона, прежде чем использовать его в popover?

Изменить: я пытался заставить angular до $apply() перед созданием popover, он работает, но генерирует ошибки JavaScript, которые не подходят для меня.

Ответы

Ответ 1

$compile позволяет использовать так называемую функцию clone attach, которая позволяет прикрепить ваши элементы к документу. Вот пример, который вы можете использовать:

var template = "<div> .. {{someCompilingStuff}} ..</div>";
var compiled = $compile(template)(cellScope, function (clonedElement) {
  cellElement.popover({
    html: true,
    placement: "bottom",
    trigger: "manual",
    content: clonedElement
  });
});

Ссылка на Angular документацию об использовании компиляции

Ответ 2

Даже если будет возможно получить уведомление, когда функция компиляции/ссылки полностью отобразит шаблон, вы все равно не будете уверены, что браузер завершит внесение изменений в макет страницы в ответ. Возможно, вы сможете исправить свою проблему, введя небольшую задержку, используя $timeout (setTimeout), прежде чем запускать всплывающее окно. От чтения ответов на есть ли обратный вызов post render для Angular JS-директивы? Я думаю, что это могло бы исправить вашу проблему.

Ответ 3

В этих случаях вы, вероятно, хотели бы использовать $timeout, чтобы исправить проблему.

Что-то вроде этого:

var template = "<div> .. {{someCompilingStuff}} ..</div>";
var compiled = $compile(template)(cellScope);
cellElement.popover({
   html: true,
   placement: "bottom",
   trigger: "manual",
   content: compiled
 });

$timeout(function(){
    cellElement.popover("show");
}, 0);

Вот пример JSFIDDLE, который я создал для вас. Посмотрите, как я показываю и скрываю popover с помощью $timeout.

Ответ 4

Я собираюсь предоставить некодовый ответ (так что вы можете копать немного больше и узнать почему - плюс я чувствую себя ленивым в этот час):

Я бы рекомендовал использовать делегирование событий с другим родительским HTML-элементом в качестве делегата, с помощью которого вы можете вызвать метод popover. Просто включите class= "popover" в любые [родительские] элементы и скомпилируйте в нем шаблон. Вы можете выполнить/вызвать метод popover для этого родительского элемента. Однако я не совсем уверен, что вам не нужны дочерние элементы (из шаблона), так как я не знаю этого плагина. Однако я бы попробовал что-нибудь другое, кроме тайм-аута.

Моя надежда заключается в том, что этот ответ (возможно, неверный) ускоряет создание авторского решения (в результате получается чистый, надежный код) от автора.

Ответ 5

В качестве предложения вы можете создать службу компилятора, в которую вставляете компиляцию и создаете метод с параметром, принимающим html и область действия.

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

сообщите мне, если он не работает для вас, я предоставил вам образцы кода.

Ответ 6

Я бы попытался обернуть компиляцию вашего шаблона внутри функции, которая возвращает обещание.

Что-то вроде этого:

function compile () {
  var deferred = $q.defer();

  /** simulate something sloooow (remove the setTimeout in your implementation) **/
  setTimeout(function () {
    deferred.resolve($compile('content')(scope));
  }, 2000);

  return deferred.promise;
}

// and then ...
compile().then(function (content) {
  element.popover({
    content: content
  });
});

'наивный' jsbin && & && & & jsfiddle (изменено @Amir's)

Я не могу гарантировать, что это сработает для вашего конкретного случая, но стоит сделать это.