David
David

Reputation: 3604

Subscribe to changes in parent component in Angular

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

Answers (2)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

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

Pradeep Prabhu B R
Pradeep Prabhu B R

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

Related Questions