Angular 5 Example - To be able to enter new item to empty list


"Angular Example - Tour of Heroes: Part 6" in the tutorial of Angular 5 has a problem to enter an item into the heros.component. This article shows a way to solve it.

The problem of heros.component

First, delete all items from the list of the heros.component.

Figure 001•Empty list

Second, enter new item in the text field and press the [add] button.

Figure 002•Entering new item

Then listed item has neither id nor name. Browser console indicates the error message like below:

body: {error: "Collection 'heroes' id type is non-numeric or unknown. Can only generate numeric ids."}

Figure 003•Blank item is inserted into the list

When the array of data comes to be empty, nothing has the id property. Then number for id does not seem to be generated and new item cannot be registered.

Use HttpClient.put() method to add an item with id

The HttpClient.put() method sets data to the specific id. Revise the HeroService.addHero() method to call the HttpClient.put() method when the data array is empty.

export class HeroService {

    // addHero(hero: Hero): Observable<Hero> {
    addHero(hero: Hero, numHeros: number): Observable<Hero> {
        let heroOvserbable;
        // return this.http.post<Hero>(this.herosUrl, hero, httpOptions)
        if (numHeros === 0) {
            hero.id = 11;
            heroOvserbable = this.http.put(this.herosUrl, hero, httpOptions)
        } else {
            heroOvserbable = this.http.post<Hero>(this.herosUrl, hero, httpOptions);
        }
        return heroOvserbable

    }

}

Since the HeroService class does not know the data array, the HerosComponent.add() method passes the Array.length property of data as an argument to call the HeroService.addHero().

export class HerosComponent implements OnInit {

    add(name: string): void {

        // this.heroService.addHero({name} as Hero)
        this.heroService.addHero({name} as Hero, this.heros.length)

    }

}

Now new item can be entered even if the list is empty. Revised example is "Angular Example - Tour of Heroes: Part 6 revised".

Overriding a method of Angular in-memory-web-api module

The reason why an id for new item is not generated when the list is empty might be based on the specification of the Angular in-memory-web-api module. BackendService.genIdDefault() method to provide the default id number calls BackendService.isCollectionIdNumeric() to make sure of id property in the collection. Only if the property exists and is numeric, new number will be provided.

The number for new entry is generated with the BackendService.genId() method which can be overridden by the InMemoryDataService class (in-memory-data.service module). This is another way to solve the problem.

The method below return the max number of ids plus one (+1) if they exists or the initial number (11) if it does not.

export class InMemoryDataService implements InMemoryDbService {

    genId(heroines: Heroine[]): number {
        return heroines.length > 0 ? Math.max(...heroines.map(heroine => heroine.id)) + 1 : 11;
    }
}

See "Tutorial example has a problem to enter new item into an empty list" and example code "Angular Example - Tour of Heroes: Part 6".