Is there a way to detect changes in ng-content?
@Component({
selector: 'example',
template: `<ng-content></ng-content>`
})
export class Example {}
@Component({
selector: 'test',
template: `
<example>
<div *ngFor="let el of elements">{{el}}</div>
</example>`
})
export class Test {
elements = [1, 2, 3];
ngOnInit() {
setInterval(() => this.elements[0] += 10, 3000);
}
}
I would like to get some information in Example class when my ng-content will change.
Here is plunker
To run the change detector manually: Inject ChangeDetectorRef service in the component. Use markForCheck in the subscription method to instruct Angular to check the component the next time change detectors run. On the ngOnDestroy() life cycle hook, unsubscribe from the observable.
By default, angular will run the change detector every time @Input() data is changed or modified. But with OnPush strategy, the change detector is only triggered if the data passed on @Input() has a new reference.
The ng-content is used when we want to insert the content dynamically inside the component that helps to increase component reusability. Using ng-content we can pass content inside the component selector and when angular parses that content that appears at the place of ng-content.
The easiest solution is to use the cdkObserveContent directive. First, you must add to the imports of the module that owns the component ObserversModule
import {ObserversModule} from '@angular/cdk/observers';
@NgModule({
imports: [
/* ...other modules you use... */
ObserversModule
],
/* ... */
})
export class MyModule { }
Then in your component's template:
<div (cdkObserveContent)="onContentChange($event)">
<ng-content></ng-content>
</div>
The event will trigger each time the content inside changes somehow and the value passed to the function is an array with all the details about what changed. The value of the data that has changed can be found in target.data
.
In your component.ts:
onContentChange(changes: MutationRecord[]) {
// logs everything that changed
changes.forEach(change => console.log(change.target.data));
}
Also, you can use as a service that gives you an Observable<MutationRecord[]>
My solution for a project is to monitor the content's innerHTML. This example is from a tooltip that shows template content. I don't really like this solution, and would be happy to have a different/better one offered. This will emit whenever there are changes.
/// tooltip.component.html
<div class="tooltip" [class.hidden]="hidden">
<div #content>
<ng-content></ng-content>
</div>
</div>
///tooltip.component.js
import { AfterContentChecked, AfterContentInit, Component, ElementRef, EventEmitter, Output, ViewChild } from "@angular/core";
@Component({
selector: "example",
templateUrl: "./tooltip.component.html",
styleUrls: ["./tooltip.component.scss"]
})
export class TooltipComponent implements AfterContentInit, AfterContentChecked {
@ViewChild("content") contentWrapper: ElementRef;
content = "";
@Output() public readonly contentChanged = new EventEmitter<string>();
ngAfterContentInit(): void {
this.content = this.contentWrapper.nativeElement.innerHTML;
this.contentChanged.emit(this.content);
}
ngAfterContentChecked(): void {
const c = this.contentWrapper.nativeElement.innerHTML;
if (c !== this.content) {
this.content = c;
this.contentChanged.emit(this.content);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With