MikePR
MikePR

Reputation: 2986

Update child component from parent in Angular

I have struggling to make it work in Angular. I have a host component (parent) which is using a child one to render a dropdown list. The source of the list is been passed from the parent. So for example, if the parent pass 5 items on the source property, the child component will render 5 options for the dropdown list.

this is part the code where I call the child component:

parent.component.html

<ng-container>
   <th mat-header-cell *matHeaderCellDef>
         <app-column-header
            [id]="column.id"
            [name]="column.name"
            [source]="myObject.options"
          ></app-column-header>
   </th>
</ng-container>

parent.component.ts

export class ParentComponent  {  

@ViewChild(ChildComponent) ChildComponent;  

 // more code

  private updateChildSource() {
    this.child.updateDataSource(myObject.options);
  }
}

This is working OK so far.

NOW, the challenges I am having is that the list of items to be passed needs to be dynamic (myObject.options). So, for example, the first time lets says I am passing 5 items. Angular takes those 5 items and render the child component properly. However, once the child component is already rendered and if I changes the source to be 2 items instead of 5 from the parent and pass the new source, the child component is not rendering the new items (2).

child.component.ts

export class ColumnHeaderComponent implements OnInit, OnChanges {
  @Input() id: string;
  @Input() name: string;
  @Input() source: any[];

 childField: any;

  ngOnInit(): void {
    const options = this.doStuffHere(this.source);
    this.childField= {
      id: this.id,
      options,
    };
  }

  updateDataSource(newSource: Option[]): void {
     console.log(`print call from parent. old options: 
     ${JSON.stringify(this.childField.options)} - new options: ${JSON.stringify(newSource)}`);
     this.source= newSource;
     const options = this.doStuffHere(this.source);
     this.childField= {
       id: id,
       options,
     };
  }

  ngOnChanges(changes: SimpleChanges) {
    console.log('changed');     
    for (const propName in changes) {
      const chng = changes[propName];
      const cur  = JSON.stringify(chng.currentValue);
      const prev = JSON.stringify(chng.previousValue);
      console.log(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
    }
  }
}

As mentioned before, the child component is receiving the original and new items, even the ngOnChanges method is capturing it and printing the values properly. But for some reason I don't know yet the child component is still rendering the old items (5) instead of the new ones (2).

Not sure, if I am missing something here? Or the question is clear enough to illustrated the problem I am facing.

Could you point me to the correct direction how to solve this? Thanks in advance.

Upvotes: 0

Views: 3515

Answers (1)

sDe
sDe

Reputation: 76

As said Marek you can directly pass the list from your parent component as the input of your child component. The [list]="list" notation is already reactive. Then you'll just have to use the list in the drop-down in your child component.

Note : Not useful here, but as @Input you can set a function instead of a variable. It will be triggered every time the input value change.

Upvotes: 3

Related Questions