Reputation: 3009
I have a component that displays a list of varieties that are retrieved from a service, as you can see here.
export class SellingMenuVarietiesComponent implements OnInit {
varieties: Variety[];
constructor(public sellingMenuService: SellingMenuService) { }
ngOnInit(): void {
this.getVarietyList();
}
// Get Variety List
getVarietyList(): void {
this.sellingMenuService.getVarieties().subscribe(res => {
this.varieties = res;
});
}
}
I have another component that removes varieties, as seen here:
export class SellingVarietyEditComponent implements OnInit {
constructor(private sellingMenuService: SellingMenuService) { }
// Remove variety
removeVariety(id: number) {
this.sellingMenuService.removeVariety(id).subscribe(res => {
this.sellingMenuService.getVarieties();
});
}
}
In this example, both components are visible on the page at the same time, so when you delete a variety, I want the list to automatically update and reflect that. Currently, the variety will successfully delete from the database, but will remain on the list until I refresh the page. Notice in the removeVariety()
function from SellingVarietyEditComponent
, I re-invoke the getVarieties()
method from my service in an attempt to get the list to update, but it doesn't work.
What am I doing wrong? How Can I accomplish this?
Here are the relevant functions from that service:
@Injectable()
export class SellingMenuService {
// Get Variety List
public getVarieties(): Observable<any> {
return this.http.get(this.varietyList).map(response => {
return response.json();
}, (error: any) => {
console.log(error);
});
}
// Remove Variety
public removeVariety(varietyId: any): Observable<any> {
return this.http.get(this.removeVarietyUrl + varietyId).map(response => {
return response;
}, (error: any) => {
console.log(error);
});
}
}
EDIT:
Attempting EventEmitter solution:
In SellingMenuService
, I added this code (Notice I added this.updateVarietyList.emit(null);
to getVarieties()
):
@Output() updateVarietyList: EventEmitter<any> = new EventEmitter();
// Get Variety List
public getVarieties(): Observable<any> {
return this.http.get(this.varietyList).map(response => {
this.updateVarietyList.emit(null);
return response.json();
}, (error: any) => {
console.log(error);
// TODO: implement error handling here.
});
}
In SellingVarietyEditComponent
, my remove button looks like this:
<a class="remove-button" (click)="removeVariety(varietyId)" (updateVarietyList)="onVarietyListUpdate($event)" >Remove</a>
And finally in SellingMenuVarietiesComponent
I added this:
onVarietyListUpdate() {
console.log('test');
this.getVarietyList();
}
This code however does not work. I don't get any errors, but the onVarietyListUpdate()
method never executes. Am I on the right path at all? How can I fix this? The example I've found are confusing and I am having trouble applying them to my code.
Upvotes: 2
Views: 1108
Reputation: 652
I just realized you have different components. So the solutions changes actually. But I have still kept the old solution which gives you a better idea on tackling the stuff if you need in the future.
NEW SOLUTION
You can make component-interactions.service.ts, in that
updateVarieties = new Subject();
updateVarieties$ = this.updateVarieties.asObservable();
getVarieties(){
this.updateVarieties.next();
}
In here,
export class SellingMenuVarietiesComponent implements OnInit {
varieties: Variety[];
constructor(private ciService:ComponentInteractionService, public sellingMenuService: SellingMenuService) { }
ngOnInit(): void {
this.ciService.updateVarieties$.subscribe(()=> {
this.getVarieyList();
});
this.getVarietyList();
}
// Get Variety List
getVarietyList(): void {
this.sellingMenuService.getVarieties().subscribe(res => {
this.varieties = res;
});
}
}
In Edit Component,
export class SellingVarietyEditComponent implements OnInit {
constructor(private ciService:ComponentInteractionService, private sellingMenuService: SellingMenuService) { }
// Remove variety
removeVariety(id: number) {
this.sellingMenuService.removeVariety(id).subscribe(res => {
this.ciService.getVarieties();
});
}
}
OLD SOLUTION: IF SINGLE COMPONENT HANDLES EDIT AND SHOW
The thing is you need to update the UI with the new data. One way to do it is return the updated varieties with the success response from backend after deleting the variety.
So, I hit the removeVariety API, perform delete operation with id, and you do something like varieties.getAll() in the backend and send the updated varieties in the success response. And then you just do
this.varieties = res;
This is simple for the Frontend to do.
Another approach is to save the id in a variable before you hit the delete API. Now you have the id you are deleting, you hit the API, it is successful and then you do
export class SellingVarietyEditComponent implements OnInit {
constructor(private sellingMenuService: SellingMenuService) { }
// Remove variety
removeVariety(id: number) {
let deleteItemId = id;
this.sellingMenuService.removeVariety(id).subscribe(res => {
if(res.status=="SUCCESS"){ /* check if it was successful.(Good practice to include that in API Response*/
this.deleteItemById(deleteItemId);
}
});
}
deleteItemById(id:number){
this.varieties.forEach((value)=> {
if(value.varietyId==id){
let index = this.varieties.indexOf(value);
if(index>-1){
this.varieties.splice(index, 1);
}
}
});
}
I think it is not a good idea to call the getVarieties again. In your code why it is not working is because it is returning you an observable and you are not subscribing to that and updating the varieties array. If you still want to call the get API. You can do
this.getVarietyList();
instead of
this.sellingService.getVarieties();
and make that function again in the edit component the same you have in other component.
Upvotes: 1
Reputation: 8986
You could use an EventEmitter
in your SellingMenuService
to emit an event when a variety
is removed/updated. Listen for this event in SellingMenuVarietiesComponent
and update your array accordingly
Upvotes: 0