Search code examples
angularrerender

How to refresh the Parent component after a button on child component is pressed? - Angular


so I am currently updating an ingredient amount in a pop-up and I want the ingredient card to rerender and show the new amount when the pop-up closes, however, I am unsure of how to achieve this.

This is my ingredient service code:

  //UPDATE
  updateAmount(id: string, newAmount: number): Observable<Ingrediant>{
    return this.http.put<Ingrediant>(`${this.url}/${id}`, {amount: newAmount});
  }

This is the ingredient component HTML:

    <div class="ingrediant-slider">
        <hr/>
        <h4 class="ingrediant-heading">Bread</h4>

        <div class="carousel">
            <img src="../../assets/arrows/left-arrow.png" class="arrow-left" (click)="scroll(-scrollAmount)">
            <img  src="../../assets/arrows/right-arrow.png" class="arrow-right" (click)="scroll(scrollAmount)">
            <div class="card" *ngFor="let breadIngrediants of breadIngrediants; let i=index" >
                <div class="top-circle">
                    <h4>{{breadIngrediants.amount}}</h4>
                </div>
                <div class="circle">
                    <img [src]="breadIngrediants.image" class="card-img" alt="Image of burger"/>
                </div>
                <h3>{{breadIngrediants.name}}</h3>
                <button (click)="showPopup = true; selectedIngrediants = breadIngrediants">Update</button>

            </div>
        </div>
    </div>

    <app-popup *ngIf="showPopup" [selectedIngrediants]="selectedIngrediants" (close)="showPopup = false" (updated)="onUpdate()"></app-popup>

This is the ingrediant .ts:

// add this method to update the ingredient list when the event is emitted
onUpdate() {
  // re-fetch the ingredient data and update the local variable
  this.ingrediantService.items$.subscribe((data) => {
    this.breadIngrediants = data;
    console.log(data);
    this.cdr.detectChanges();
  });
}

This is the pop-up HTML:

 <div class="popup"[style.top.px]="getYPosition(selectedIngrediants)">
    <div class="left-pannel">
        <div class="circle">
            <img [src]="selectedIngrediants.image" class="card-img" alt="Image of burger"/>
        </div>
    </div>
    <div class="right-pannel">
        
    </div>
    <h2>{{ selectedIngrediants.name }}</h2>
    <p>{{ getDescription() }}</p>
    <h4>Amount</h4>
    <input type="number" matInput placeholder="0" color="accent"
    [value]="selectedIngrediants.amount"
    (change)="detectAmountChange($event)"
    > 

    <button class="primary-btn" (click)="updateAmount(selectedIngrediants._id!); closePopup();">Update</button>
    <button class="secondary-btn"  (click)="closePopup()" >Cancel</button>
  </div>

and the pop-up ts:

//changes newAmountPlaceholder to current input value
detectAmountChange(e: any){
  this.newAmountPlaceholder = +e.target.value
}


@Output() updated: EventEmitter<void> = new EventEmitter<void>();


updateAmount(id: string) {
  this.ingrediantService.updateAmount(id, this.newAmountPlaceholder).subscribe((selectedIngrediant) => {
    console.log(selectedIngrediant.amount);
    this.updated.emit(); // emit the event when the update is successful
  });
}

Solution

  • Your code should work, even though it's not a very clean approach. One thing, I guess the popup is being closed before the end of the Http request so the (update) is never called.

    What i recommand is letting the parent component handle the Http Request and leave the Popup to only deal with input.

    In pop-up.ts

    @Output() updated: EventEmitter<any> = new EventEmitter<any>();
    
    
    updateAmount(id: string) {
      this.updated.emit({id: id, amount: this.newAmountPlaceholder});
    
    }
    

    In ingrediant.ts:

    onUpdate(popupData:any) {
      this.ingrediantService.updateAmount(popupData.id, popupData.amount).subscribe(() => {
        //after saving refresh
        this.ingrediantService.items$.subscribe((data) => {
          this.breadIngrediants = data;
          console.log(data);
          this.cdr.detectChanges();
        });
      });
    }
    

    and finally update the html in ingerdiant

    <app-popup *ngIf="showPopup" [selectedIngrediants]="selectedIngrediants" (close)="showPopup = false" (updated)="onUpdate($event)"></app-popup>
    

    Hope this works :)