I have made a basic app for managing a database. The data is presented in a table and buttons for deleting each item. For some reason, when deleting an item, the data does not refresh on the first click of the button but the second. The second time the button is clicked, the console outputs a 404 error for the http request, because the item doesn't exist.
I'm wondering why the data doesn't reload before then. This is my component:
import { Component, OnInit } from '@angular/core';
import { BackendService } from 'src/app/backend.service';
import { ICity } from '../interfaces/city';
import { ICountry } from '../interfaces/country';
@Component({
selector: 'app-cities',
templateUrl: './cities.component.html',
styleUrls: ['./cities.component.css']
})
export class CitiesComponent implements OnInit {
public countries: ICountry[] = [];
public cities: ICity[] = [];
constructor(private _backendService: BackendService) { }
ngOnInit(): void {
this.loadCities();
this.loadCountries();
}
loadCities() {
this._backendService.getCities().subscribe(data => {
this.cities = JSON.parse(JSON.stringify(data)).cities;
});
}
loadCountries() {
this._backendService.getCountries().subscribe(data => {
this.countries = JSON.parse(JSON.stringify(data)).countries;
});
}
submit(city: ICity) {
this.remove(city);
this.ngOnInit();
}
remove(city: ICity): void {
this.countries.forEach((cn) => {
if (cn.majorCities.find(c => c.name == city.name)) {
console.log(cn);
this._backendService.removeCity(cn.name.toLowerCase(), city.name.toLowerCase()).subscribe(data => console.log(data));
}
});
}
}
Template:
<h1>Cities</h1>
<tbody>
<tr>
<td><h3>City</h3></td>
<td><h3>Population</h3></td>
<td><h3>Area in km²</h3></td>
<td><h3>City Rank</h3></td>
</tr>
<tr *ngFor="let city of cities">
<td>{{ city.name }}</td>
<td>{{ city.population }}</td>
<td>{{ city.area }}</td>
<td>{{ city.rank }}</td>
<button type="button" (click)="submit(city)">Delete</button>
</tr>
</tbody>
You may have a race condition here. You're submitting a request for deletion, but performing a refresh before a response has been received and handled. When working with RxJS subscriptions, you can do the following...
this._backendService.removeCity(cn.name.toLowerCase(), city.name.toLowerCase()).subscribe(
// This is the callback for when the response was successful.
// No error was caught during the request.
(data) => {
// You can attempt a refresh here because we know the request has
// completed and the row was deleted.
this.refresh();
},
// This is the callback for when the response was not successful.
// The backend service threw some sort of error, or the code ran into an error
// during execution. You can handle the error here (display some message).
(error) => {
// Do something in response to the error.
}
// This is the code to run when the Observable has communicated that it has
// completed. The observable has said "I'm done sending messages, there will be
// no more," so do whatever you need to in response to that.
() => {
// Do something...
}
);
I also would not recommend using ngOnInit for your refresh operation as it is a reserved method used by Angular; you may find that, by calling ngOnInit, more is being done than you might think.
ngOnInit() {
this.refresh();
}
public refresh(): void {
// Your refresh logic here.
}