У меня есть угловой шаблон в DOM. Когда мой контроллер получает новые данные от службы, он обновляет модель в области $ и повторно отображает шаблон. Пока все хорошо.
Проблема заключается в том, что мне нужно также выполнить дополнительную работу после того, как шаблон был перерисован и находится в DOM (в данном случае плагин jQuery).
Кажется, что должно быть событие для прослушивания, например AfterRender, но я не могу найти ничего подобного. Может быть, директива была бы способом пойти, но, похоже, она тоже сработала слишком рано.
Вот jsFiddle с изложением моей проблемы: Fiddle-AngularIssue
== ОБНОВЛЕНИЕ ==
Основываясь на полезных комментариях, я соответственно переключился на директиву для обработки манипуляций с DOM и реализовал модель $ watch внутри директивы. Тем не менее, я все еще имею ту же самую проблему с базой; код внутри события $ watch запускается до того, как шаблон был скомпилирован и вставлен в DOM, поэтому плагин jquery всегда оценивает пустую таблицу.
Интересно, что если я уберу асинхронный вызов, все будет работать нормально, так что это шаг в правильном направлении.
Вот мой обновленный Fiddle, чтобы отразить эти изменения: http://jsfiddle.net/uNREn/12/
источник
Ответы:
Этот пост старый, но я изменил ваш код на:
см. jsfiddle .
Я надеюсь, что это поможет вам
источник
Во-первых, правильное место, чтобы связываться с рендерингом - это директивы. Мой совет - обернуть DOM-манипуляции с плагинами jQuery такими директивами, как эта.
У меня была такая же проблема, и я придумал этот фрагмент. Он использует
$watch
и$evalAsync
для обеспечения того, чтобы ваш код выполнялся после того, как директивы, такие какng-repeat
были разрешены, и шаблоны, подобные{{ value }}
полученным.Надеюсь, что это поможет вам предотвратить некоторую борьбу.
источник
link
функцию сtemplateUrl
.Следуя совету Миско, если вы хотите асинхронную операцию, то вместо $ timeout () (что не работает)
используйте $ evalAsync () (который работает)
Скрипки . Я также добавил ссылку «удалить строку данных», которая изменит $ scope.assignments, имитируя изменение данных / модели, чтобы показать, что изменение данных работает.
Раздел Runtime на странице концептуального обзора объясняет, что evalAsync следует использовать, когда вам нужно, чтобы что-то произошло за пределами текущего фрейма стека, но до того, как браузер отобразит. (Догадываясь здесь ... «текущий фрейм стека», вероятно, включает обновления Angular DOM.) Используйте $ timeout, если вам нужно, чтобы что-то произошло после рендеринга браузера.
Однако, как вы уже узнали, я не думаю, что здесь есть необходимость в асинхронной операции.
источник
$scope.$evalAsync($scope.assignmentsLoaded(data));
не имеет никакого смысла ИМО. Аргументом для$evalAsync()
должна быть функция. В вашем примере вы вызываете функцию в тот момент, когда функция должна быть зарегистрирована для последующего выполнения.Я обнаружил, что самое простое (дешевое и веселое) решение - просто добавить пустой диапазон с помощью ng-show = "someFunctionThatAlwaysReturnsZeroOrNothing ()" в конце последнего отображенного элемента. Эта функция будет запускаться, когда нужно проверить, должен ли отображаться элемент span. Выполните любой другой код в этой функции.
Я понимаю, что это не самый элегантный способ делать вещи, однако, он работает для меня ...
У меня была похожая ситуация, хотя она была слегка изменена, когда мне нужно было удалить индикатор загрузки, когда анимация началась, на мобильных устройствах angular инициализировался намного быстрее, чем отображаемая анимация, и использование ng-cloak было недостаточно, так как индикатор загрузки был удалены задолго до того, как какие-либо реальные данные были отображены. В этом случае я просто добавил функцию return 0 к первому отображаемому элементу, и в этой функции перевернул var, который скрывает индикатор загрузки. (конечно, я добавил ng-hide к индикатору загрузки, запускаемому этой функцией.
источник
$anchorScroll
было вызывать встроенный сервис после рендеринга DOM, и, похоже, ничего не помогло, кроме этого. Взломать, но работает.Я думаю, что вы ищете $ evalAsync http://docs.angularjs.org/api/ng.$rootScope.Scope#$evalAsync
источник
Наконец, я нашел решение, я использовал REST-сервис для обновления своей коллекции. Чтобы преобразовать датируемый jquery, необходимо выполнить следующий код:
источник
Мне приходилось делать это довольно часто. У меня есть директива, и мне нужно сделать некоторые вещи jquery после того, как модель полностью загружена в DOM. поэтому я поместил свою логику в ссылку: function из директивы и обернул код в setTimeout (function () {.....}, 1); setTimout сработает после загрузки DOM, и 1 миллисекунда - это самое короткое время после загрузки DOM до выполнения кода. кажется, это работает для меня, но я бы хотел, чтобы angular вызывал событие, как только шаблон был загружен, чтобы директивы, используемые этим шаблоном, могли выполнять jquery и получать доступ к элементам DOM. надеюсь это поможет.
источник
Вы также можете создать директиву, которая запускает ваш код в функции ссылки.
Посмотрите, что ответ stackoverflow .
источник
Ни $ scope. $ EvalAsync (), ни $ timeout (fn, 0) не работали для меня надежно.
Я должен был объединить два. Я сделал директиву и также поставил приоритет выше значения по умолчанию для хорошей меры. Вот директива для этого (заметьте, я использую ngInject для внедрения зависимостей):
Чтобы вызвать директиву, вы должны сделать это:
Если вы хотите вызвать его после выполнения ng-repeat, я добавил пустой диапазон в ng-repeat и ng-if = "$ last":
источник
В некоторых сценариях, когда вы обновляете сервис и перенаправляете на новое представление (страницу), а затем ваша директива загружается до обновления ваших сервисов, вы можете использовать $ rootScope. $ Broadcast, если ваш $ watch или $ timeout терпит неудачу
Посмотреть
контроллер
директива
источник
Я пришел с довольно простым решением. Я не уверен, является ли это правильным способом, но это работает в практическом смысле. Давайте прямо посмотрим, что мы хотим сделать. Например, в директиве, включающей некоторые
ng-repeat
s, я бы следил за длиной текста (у вас могут быть другие вещи!) Абзацев или всего html. Директива будет выглядеть так:Обратите внимание, что код на самом деле выполняется после изменения рендеринга, а скорее полный рендеринг. Но я думаю, что в большинстве случаев вы можете справиться с ситуациями, когда происходят изменения рендеринга. Также вы можете подумать о сравнении этой
p
длины (или любой другой меры) с вашей моделью, если вы хотите запускать код только один раз после завершения рендеринга. Я ценю любые мысли / комментарии по этому поводу.источник
Вы можете использовать модуль jQuery Passthrough утилит angular-ui . Я успешно связал плагин карусели jQuery touch с некоторыми изображениями, которые я извлекаю из асинхронного веб-сервиса и отображаю их с помощью ng-repeat.
источник