I have the following in my component.ts file:
import {Component, OnInit} from '@angular/core';
import {IBook} from "../../models/book.model";
import {ActivatedRoute} from "@angular/router";
import {BooksService} from "../../services/books.service";
import {BookGenre} from "../../enums/book-genre";
@Component({
selector: 'bookstore-edit-book',
templateUrl: './edit-book.component.html',
styleUrl: './edit-book.component.css'
})
export class EditBookComponent implements OnInit{
genreIds: number[] = [];
bookGenres: typeof BookGenre = BookGenre;
book: IBook = null!;
selectedGenre: number = 0;
constructor(
private booksService: BooksService,
private route: ActivatedRoute) {
this.genreIds = Object.values(BookGenre)
.filter(value => !isNaN(Number(value)))
.map(Number);
}
ngOnInit() {
this.route.params.subscribe((params) => {
this.booksService.getBook(params['id']).subscribe(book => {
this.book = book;
this.selectedGenre = book.genre;
})
})
}
}
And this in my HTML template:
<div class="form-group">
<label for="genre">Genre</label>
<select id="genre" [(ngModel)]="selectedGenre">
<option *ngFor="let genreId of genreIds"
[ngValue]="genreId">{{bookGenres[genreId]}}</option>
</select>
</div>
When I load the page the select dropdown contains all the correct enum values as below:
However, when the book details are loaded, the dropdown is never updated, it is blank (i.e. nothing selected). Shouldn’t this update when the selectedGenre
value is changed from the subscription to the getBook
observable? The other book details are all updated fine except this?
2
Answers
I've since found out that
[(ngModel)]
also requires an HTMLname
attribute to be present, so the HTML should have read like this:This is now working properly and binding is working both ways.
We can use
[value]
instead of[ngValue]
since it generally has this problem!When you need the entire object, use
[ngValue]
when you need a string or number use[value]
! Overall just stick to[value]
and you will be fine!Stackblitz Demo