Angular - ng-if - как вызвать обратный вызов после создания шаблона ng-if
в Angular, мне нужно вызвать функцию после того, как элемент с определенным классом был загружен.
Отображение элемента управляется через ng-if = 'expr'. Значение $scope.expr устанавливается после ответа какого-либо ajax-вызова.
Теперь, если я попытаюсь поставить $watch на expr или использовать $evalAsync. это не работает. вероятно, причина в том, что эти события выполняются до фактической работы шаблона.
Вот пример кода: http://jsbin.com/kuyas/1/edit
Здесь мне нужна функция обратного вызова на ng - если это выполняется после того, как шаблон визуализировался.
Ответы
Ответ 1
Проблема заключалась в том, что нет способа узнать, выполняется ли angular с циклом дайджеста, гарантируя, что все элементы были отображены.
Чтобы решить эту проблему, было два варианта
- Оберните свою функцию обратного вызова в директиве. включить эту директиву в ng-if. и сделать это выражение истинным только тогда, когда вы хотите, чтобы ваш обратный вызов выполнялся.
- Вызовите функцию обратного вызова внутри,
setTimeOut(function(){ ... }, 0);
, поскольку по умолчанию браузер сохраняет все события в очереди, поэтому, когда цикл digest запущен, ваша функция обратного вызова войдет в очередь и будет выполнена, как только цикл переполнения закончится.
Ответ 2
Один из возможных ответов - создать директиву, которая сделает все, что вы хотите сделать. Если вы затем используете эту директиву только в разделе HTML, управляемом ng-if, тогда директива будет неактивной, пока выражение ng-if не будет истинным.
Будет ли это делать то, что вы хотите?
Ответ 3
Самое простое решение, на мой взгляд, состоит в следующем:
<div ng-if="sectionActivated">
<div ng-init="callBack()"></div>
</div>
Ваш обратный вызов будет вызван только тогда, когда визуализируется то, что влияет на ng-if
.
Ответ 4
Директива может выглядеть примерно так:
import * as angular from 'angular';
class OnFinishRenderDirective implements angular.IDirective {
public restrict = 'A';
public replace = false;
public link = (
scope: any,
// scope: angular.IScope,
element: angular.IAugmentedJQuery,
attr: any,
modelCtrl: any,
link: angular.ITemplateLinkingFunction ) => {
if ( scope.$last === true ) {
this.$timeout(() => {
scope.$emit( 'elementRendered' );
} );
}
}
constructor( private $timeout: angular.ITimeoutService ) { }
}
export function onFinishRenderFactory(): angular.IDirectiveFactory {
var directive = ( $timeout: angular.ITimeoutService ) => new OnFinishRenderDirective( $timeout );
directive.$inject = [ '$timeout' ];
return directive;
}
Вам нужно будет импортировать его и добавить в свой модуль
import { onFinishRenderFactory } from './onFinishRender/onFinishRender.directive';
angular.module( 'yourModule', [] )
.directive( 'onFinishRender', onFinishRenderFactory() )
Затем вы можете использовать директиву где-нибудь в своей разметке, чтобы выдать событие, когда была предоставлена директива.
<div onFinishRender>I am rendered</div>
Вы даже можете добавить дополнительный атрибут в директиве DIV, которую затем вы можете захватить из объекта ATTR в функции ссылок и добавить к своей функции $emit, чтобы идентифицировать этот конкретный DIV, который будет отображаться.
Отвечает ли это на ваш вопрос?