当元素通过 ngIf 变得可见时触发事件
Trigger event when element becomes visible with ngIf
我有一些 divs 与 ngIf,我只是想有一种方法来知道特定的 div 是否是 visible/active 现在就像像焦点(它不起作用)之类的事件触发器,对于这个事件,我将设置一个变量或其他东西。
<div *ngIf="test === true" (focus)="myVariable = true">
</div>
您的 div 将在更改检测被触发后呈现并可见。当检测到更改时,整个生命周期再次 运行。
如果你想运行 一些东西,你应该挂钩生命周期的事件之一。我建议 AfterViewInit
。
现在您知道怎么做了,让我们看看您应该怎么做。
在您的情况下,您应该使用模板引用创建 div。这将允许您引用该元素,并使您能够检查显示或隐藏了哪个 div。
Here is a stackblitz 向您展示了它是如何工作的,这是代码:
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;
}
我想以 Rachit 的回答为基础。
<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-container 中,这样它就不会影响 DOM 并且在呈现测试后是 运行 。
一个解决方案是使用 @ViewChildren
并订阅 ngAfterViewInit()
中 QueryList
的 changes
Observable,同时避免 ExpressionChangedAfterItHasBeenCheckedError
(这例如,当 div 可见时,如果您想更改模板中使用的 属性,则会发生这种情况)您可以像这样使用 ChangeDetectorRef
的 detectChanges()
:
@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();
}
}
我有一些 divs 与 ngIf,我只是想有一种方法来知道特定的 div 是否是 visible/active 现在就像像焦点(它不起作用)之类的事件触发器,对于这个事件,我将设置一个变量或其他东西。
<div *ngIf="test === true" (focus)="myVariable = true">
</div>
您的 div 将在更改检测被触发后呈现并可见。当检测到更改时,整个生命周期再次 运行。
如果你想运行 一些东西,你应该挂钩生命周期的事件之一。我建议 AfterViewInit
。
现在您知道怎么做了,让我们看看您应该怎么做。
在您的情况下,您应该使用模板引用创建 div。这将允许您引用该元素,并使您能够检查显示或隐藏了哪个 div。
Here is a stackblitz 向您展示了它是如何工作的,这是代码:
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;
}
我想以 Rachit 的回答为基础。
<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-container 中,这样它就不会影响 DOM 并且在呈现测试后是 运行 。
一个解决方案是使用 @ViewChildren
并订阅 ngAfterViewInit()
中 QueryList
的 changes
Observable,同时避免 ExpressionChangedAfterItHasBeenCheckedError
(这例如,当 div 可见时,如果您想更改模板中使用的 属性,则会发生这种情况)您可以像这样使用 ChangeDetectorRef
的 detectChanges()
:
@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();
}
}