Reputation: 3604
I've a parent component which hosts a list of child components. This children are create dynamically and can be of any type.
So, what I'm doing is using an ng-container
as host in the parent component, create the child components with ComponentFactoryResolver
and then update some properties in the child component using ```(component.instance as any).id = host.id;````
Here is the code for parent component (it's a table with some rows):
<tr class="table-collapse__item" [class.active]="company === selected">
<td [attr.colspan]="getItemColspan()">
<ng-container host [id]="name" [selected]="isSelected"></ng-container>
</td>
</tr>
host
is a directive
@Directive({
selector: '[host]'
})
export class Host implements OnChanges {
@Input() id: any;
@Input() selected: boolean;
constructor(public viewRef: ViewContainerRef) {}
}
and finally how to create the components and update the properties
@ViewChildren(Host) hosts: QueryList<Host>;
constructor(private resolver: ComponentFactoryResolver,
private cd: ChangeDetectorRef) {}
ngAfterViewInit() {
if (this.hosts) {
const componentFactory = this.resolver.resolveComponentFactory(this.inner);
this.hosts.forEach((host: Host) => {
const component = host.viewRef.createComponent(componentFactory);
(component.instance as any).id = host.id;
(component.instance as any).selected = host.selected;
});
this.cd.detectChanges();
}
}
Now, my question. I need the child component to react to changes in its properties, but as its properies are not Inputs but just basic properties, I can´t use ngOnChanges inside the childComponent. So it's there a way I can subscribe from the child component to changes in the parent component?
I can use ngOnChanges in the Host directive and update the properties in the component, but how to then trigger some code in the child component?
I have a plunker to test it. When clicking on data1, data2, data3 or data4, the row below should collapse or expande.
Thanks.
Upvotes: 7
Views: 3506
Reputation: 657288
Child components can't listen to changes in the parent, but you can notify them about changes by calling a method on the children instead:
components = [];
ngAfterVeiwInit() {
if (this.hosts) {
const componentFactory = this.resolver.resolveComponentFactory(this.inner);
this.hosts.forEach((host: Host) => {
const component = host.viewRef.createComponent(componentFactory);
(component.instance as any).id = host.id;
(component.instance as any).selected = host.selected;
this.components.push.components();
});
this.cd.detectChanges();
}
}
ngOnChanges() {
this.components.forEach((c) => {
c.instance.ngOnChanges(); // or any other method the child comonents have
})
}
Upvotes: 4
Reputation: 428
You can use event emitter in your child component and access the function in parent component
https://angular.io/docs/ts/latest/api/core/index/EventEmitter-class.html https://toddmotto.com/component-events-event-emitter-output-angular-2
Upvotes: -1