Search code examples
angularangular7

How to populate Angular nested component in ngFor loop?


I have a nested component in html side like following:

<main>
   <ng-content *ngFor="let item in data">
     <car *ngIf="item.type=='car'"></car>
     <plane *ngIf="item.type=='car'"></plane>
   </ng-content>
</main>

My car and plane components are implemented a base cehicle class.

export abstract class BaseVehicleComponent{
    onVehicleCreated(){
        console.log("on vehicle created.")
    }
}

When a vehicle created, I want to populate an event in main component.

@Component({
   selector: 'main',
})
export class MainComponent{

     @Output() vehicleCreated = new EventEmitter<void>();

}

And hml updated like this:

<main (vehicleCreated)="onVehicleCreated($event)">
   <ng-content *ngFor="let item in data">
     <car *ngIf="item.type=='car'"></car>
     <plane *ngIf="item.type=='car'"></plane>
   </ng-content>
</main>

but base methot does not fire.


Solution

  • BaseVehicleComponent should have EventEmitter not MainComponent.

    BaseVehicleComponent:

    export abstract class BaseVehicleComponent{
       @Output() vehicleCreated = new EventEmitter<void>();
    }
    

    MainComponent should have onVehicleCreated() function not BaseVehicleComponent.

    MainComponent:

    export class MainComponent{  
      onVehicleCreated(){
        console.log("on vehicle created.")
      }
    }     
    

    In car or plane components' ngOnInit() method call event emitter's emit() method.

    this.vehicleCreated.emit();
    

    Modify MainComponent's template to be

    <ng-container *ngFor="let item in data">
      <car *ngIf="item.type=='car' (vehicleCreated)="onVehicleCreated($event)"></car>
      <plane *ngIf="item.type=='plane' (vehicleCreated)="onVehicleCreated($event)"></plane>
    </ng-container>
    

    Live demo on StackBlitz: https://stackblitz.com/edit/angular-thvzue

    For more info, check out my answer on communication between parent and child components.