AngularJS: обратный вызов после рендера (работа с DOM после рендера)

Как запустить метод $scope.myWork() после шаблона рендеринга? Я хочу установить $scope.value, и после этого мне нужно что-то изменить с помощью JQuery (например, в DOM содержимого шаблона). $scope.$watch('value', function (){....}) работает "до" рендеринга (DOM шаблона еще недоступен). Спасибо.

Ответ 1

Создайте directive, который запускает ваш код в функции ссылки. Функция ссылки вызывается после создания шаблона.

Чтобы получить представление, см. ng-click.

Ответ 2

Я использую terminal и transclude в директиве атрибута для вызова метода с областью действия после обновления модели и представления (в моем случае для изменения размера iframe после $Resource.query):

.directive('postRender', [ '$timeout', function($timeout) {
var def = {
    restrict : 'A', 
    terminal : true,
    transclude : true,
    link : function(scope, element, attrs) {
        $timeout(scope.resize, 0);  //Calling a scoped method
    }
};
return def;
}])

Таймаут $- черная магия. Должно быть возможно объявить JS-метод как значение атрибута, а $проанализировать его.

Поэтому я использую его в ng-repeat (в моем случае дерево рекурсивно рекурсивно):

<div post-render ng-repeat="r in regions | orderBy:'name'" ng-include="'tree_region_renderer.html'">

Ответ 3

У меня также была эта проблема, другие решения не работали хорошо для меня, и это казалось тем, что, должно быть, решил решить. Быстрый анализ Скриптов клиентской стороны-протокатора показывает, что он использует angular.getTestability(element) для того, чтобы знать, когда действительно запускать тесты. Метод ожидает, пока не будут ожидающие ожидания или http-запросы, а затем запустит ваш обратный вызов. Здесь моя директива:

export function afterRender ($timeout) {
"ngInject";
  return {
      restrict: 'A',
      terminal: true,
      link: function (scope, element, attrs) {
        angular.getTestability(element).whenStable(function() {
          console.log('[rendered]');
        });
      }
  };
}

Ответ 4

Ответ Jens выше будет работать, но обратите внимание, что в новых версиях AngularJS (например, 1.2.3) вы не можете иметь эту директиву postRender в сочетании с ng-repeat в качестве атрибутов одного и того же тега, поскольку оба они переключили: true. В этом случае вы либо должны удалить transclude, либо иметь отдельный тег с атрибутом директивы postRender.
Также имейте в виду приоритет атрибутов при использовании терминала: true, так как вы можете получить неэффективный атрибут из-за более высокого приоритета в одном и том же теге.

Ответ 5

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

Прикрепите обработчик ng-init к элементу DOM и в функции обработчика, используйте $timeout для выполнения выполнения. Пример:

HTML:

<div ng-init="foo()">

JS:

$scope.foo = function() {
    $timeout(function() {
        // This code runs after the DOM renders
    });
});