Angular: запускает событие, когда элемент становится видимым с помощью ngIf
У меня есть некоторые div с ngIf, я просто хочу иметь способ узнать, является ли конкретный div тот, который видим / активен сейчас, как триггер события, как фокус (он не работает) или что-то, и с это событие, я буду устанавливать переменную или что-то.
<div *ngIf="test === true" (focus)="myVariable = true">
</div>
4 ответа
Ваш div будет визуализирован и видим после запуска обнаружения изменений. При обнаружении изменения весь жизненный цикл запускается снова.
Если вы хотите что-то запустить, вам нужно подключить одно из событий жизненного цикла. Я предлагаю AfterViewInit
,
Теперь, когда вы знаете, как, давайте посмотрим, что вы должны делать.
В вашем случае вы должны создать div с ссылками на шаблоны. Это позволит вам иметь ссылку на элемент и даст вам возможность проверить, какой div показан или скрыт.
Вот стек, который показывает вам, как он работает, а вот код:
import { Component, ViewChildren, QueryList, ElementRef } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<div *ngFor="let item of [0, 1, 2, 3, 4, 5]; let i = index">
<span *ngIf="i === show" #shownDiv [id]="'div-' + i">{{ item }}</span>
</div>
`
})
export class AppComponent {
name = 'Angular 6';
show = 0;
@ViewChildren('shownDiv') divs: QueryList<ElementRef>;
ngOnInit() {
setInterval(() => {
this.show++;
if (this.show > 5) {
this.show = 0;
}
}, 1000);
}
ngAfterViewChecked() {
let shown = this.divs.find(div => !!div);
console.log('DIV shown is ' + (shown.nativeElement as HTMLSpanElement).id);
// Now that you know which div is shown, you can run whatever piece of code you want
}
}
Это может быть возможным обходным путем. Это может быть не лучшим, но будет работать.
В HTML-файл,
<div *ngIf="show()"> </div>
В файле компонента TS,
show(){
if(test){ //condition for showing the div
myVariable = true;
return true;
}
else
return false;
}
Я хотел бы развить ответ Рахита.
<div *ngIf="test"><ng-container *ngIf="runShow && show()"></ng-container></div>
и в компоненте
this.runShow = true;
//show always returns true.
show() {
//Return if not running. Shouldn't be needed as runShow proceeds show in the template.
if(!this.runShow) {
return true;
}
//Do modifications...
this.runShow = false;
return true;
show()
будет запускаться только в том случае, если тест верен, и выключится после одной итерации (конечно, вы можете изменить this.runShow
основываться на чем-то). Важный момент заключается в том, что покаthis.runShow == false
, это будет выполняться каждый раз, когда компонент обнаруживает изменение, не больше и не меньше. Мы помещаем show() в его собственный ng-контейнер, чтобы он не влиял на DOM и запускался после рендеринга теста.
Решением было бы использовать
@ViewChildren
и подписаться на
changes
Наблюдаемый
QueryList
в
ngAfterViewInit()
, также во избежание
ExpressionChangedAfterItHasBeenCheckedError
(это происходит, если, например, вы хотите изменить свойство, которое используется в шаблоне, когда div отображается), вы можете использовать
detectChanges()
из
ChangeDetectorRef
как это:
@Component({
selector: "my-app",
template: `
<div *ngIf="num % 10 === 0" #doSomethingWhenVisibleDIV>
Show some content
</div>
<div *ngIf="showOtherDiv">Show different content here</div>
`,
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
num: number = 0;
showOtherDiv: boolean = false;
private subscription: Subscription;
@ViewChildren("doSomethingWhenVisibleDIV") divs: QueryList<ElementRef>;
constructor(private changeDetectorRef: ChangeDetectorRef) {}
ngOnInit() {
setInterval(() => this.num++, 1000);
}
ngAfterViewInit() {
this.subscription = this.divs.changes.subscribe({
next: () => {
if (this.divs.length > 0) {
this.showOtherDiv = !this.showOtherDiv;
this.changeDetectorRef.detectChanges();
}
}
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}