Issue
I need to listen to class name changes on a element being replaced by the <ng-content>. I have tried many ways and the only way I found for this is by using setInterval which I think is not a good practice. Suppose I will inject an input element inside the <app-child> component
@Component({
selector: 'app-parent',
template: `
<app-child>
<input type="text">
</app-child>
`
})
export class ParentComponent implements OnInit {
ngOnInit() { }
}
And that I want to do something inside child.component.ts whenever the class attribute of the input change:
@Component({
selector: 'app-child',
template: `<ng-content select="input"></ng-content>`
})
export class ChildComponent implements OnInit {
@ContentChild(HTMLInputElement) input: any;
ngOnInit() {
setInterval(() => {
const { className } = this.input.nativeElement;
console.log(className);
}, 500);
}
}
This approach manages to detect the class change but the problem with setInterval is that that callback will be running on background every 500 milliseconds, is there another way to detect the change?
Note: I've already tried the hook ngAfterContentChecked which is ran automatically after any change detection but inside I don't have access to the latest change on this.input.nativeElement.className as if this function was executed before the value was changed.
Solution
You can use the MutationObserver Api
Something like this:
ngAfterContentInit(): void {
this.changes = new MutationObserver((mutations: MutationRecord[]) => {
mutations.forEach((mutation: MutationRecord) => {
// this is called twice because the old class is removed and the new added
console.log(
`${mutation.attributeName} changed to ${this.input.nativeElement.classList}`
);
});
});
this.changes.observe(this.input.nativeElement, {
attributeFilter: ['class'],
});
}
Here is a stackblitz with it running https://stackblitz.com/edit/angular-ivy-tz5q88?file=src%2Fapp%2Fchild.component.ts
Answered By - Luiz Avila
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.