简体   繁体   中英

How to emit data from Parent Component to a specific Dynamically created Child Component?

Minimal Representation: https://stackblitz.com/edit/angular-bs4ppy

I am generating child(card) components using *ngFor loop on an array property cards of the config. As you can see in the below appcomponent.html

Problem Statement: On the click of the button on parent (appcomponent) I want to send the first three children a value specific to them.

For ex: If app component has 8 child components. On button click I want to pass 1 to child 1, 2 to child 2 and 3 to child 3. Other child components should not get any message.

Now the problem is that if I send a message using subject and listen to it inside child component, all the child components will get the same message instead of message directed to each child. If I emit x from parent, and console log it within child inside subscribe(), I will get x times.

It is hard for me to put it in words so I have added code and also created a stackblitz sample.

Please click on load more button and check the console to understand the problem.

appComponent.html :

<div *ngFor="let cardConfig of carouselConfig.cards">
  <app-card [cardConfig]="cardConfig"></app-card>
</div>
<button (click)="loadMore()"> load more</button>

AppComponent.ts

export class AppComponent {
  name = "Angular";
  carouselConfig: any;   
  cardsTable:any;

  constructor(private carouselService:CarouselService) {
    this.carouselConfig = carouselConfig;
      this.cardsTable =  _.cloneDeep(this.carouselConfig.cards.map(obj=> ({ ...obj, Loaded: 'false' })));
  }

  loadMore() {
    var cardsToLoad = this.cardsTable
      .filter(this.loadedCardsFilter)
      .slice(0, 3);

    console.log("cardsTable", cardsToLoad);

    this.carouselService.endReachedSubject.next(cardsToLoad);
  }
  loadedCardsFilter(item) {
    return item.Loaded == "false";
  }
}

Config.ts

export const carouselConfig = {
  size: 3,
  height: "200px",
  width: "600px",
  cards: [
    {
      Id: "1",
      dataModel: "xyz",
      manifestPath: "customcards/packingslip",      
    },
   {
      Id: "2",
      dataModel: "xyz",
      manifestPath: "customcards/packingslip",      
    },
{
      Id: "3",
      dataModel: "xyz",
      manifestPath: "customcards/packingslip",      
    },
   {
      Id: "4",
      dataModel: "xyz",
      manifestPath: "customcards/packingslip",      
    }
  ]
};

Carousel Service

export class CarouselService {
  endReachedSubject: BehaviorSubject<any> = new BehaviorSubject("start");
  constructor() { }
}

2 strategies are possible here:

  • Pass an input with the index to the <app-card> and in your observable, send an object with as a key, the index, and as a value, the data you want to send:
*ngFor="let cardConfig of carouselConfig.cards; let i= index"
..
<app-card [index]="index">
this.carouselService.endReachedSubject.next({
 0: [..., ..., ...],
 1: [...],
 2: []
});

and in your card:

this.carouselService.endReachedSubject.pipe(
  map(data => data[this.index])
).subscribe( ...)
  • The other strategy is to enhance carouselConfig.cards with the value and pass the data in input in your component.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM