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
});
}
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 :)