I have two dropdowns in separate child components, that are contained within a parent form component. The form component also contains an input field for quantity. On submit, the value for the quantity returns just fine, but the values from the dropdowns return undefined.
This is my form component:
export class BestelformulierComponent {
selectedGroente: { naam: string, prijs: number };
selectedWinkel: {naam:string};
aantal: number;
onGroenteSelected(groente: {naam:string, prijs:number}) {
this.selectedGroente = groente;
}
onWinkelSelected(winkel: {naam:string}){
this.selectedWinkel = winkel;
}
onSubmit() {
console.log(this.selectedWinkel, this.aantal, this.selectedGroente);
}
}
And the corresponding form html:
<h1>Bestelformulier</h1>
<form #bestelFormulier="ngForm" (ngSubmit)="onSubmit()">
<app-winkels (winkelSelected)="onWinkelSelected($event)"></app-winkels>
<app-groenten (groenteSelected)="onGroenteSelected($event)"></app-groenten>
<div>
<label>Aantal/gewicht (stuk)</label>
<input type="number" required [(ngModel)]="aantal" name="aantal">
</div>
<button type="submit" >Bestel</button>
</form>
The dropdown for stores:
export class WinkelsComponent implements OnInit{
winkels: Winkel[] = [];
@Output() winkelSelected = new EventEmitter<{naam:string}>();
ngOnInit(): void {
this.getWinkels();
}
getWinkels(): void {
this.winkelService.getWinkels()
.subscribe(winkels => this.winkels = winkels);
}
selectedWinkel: {naam:string}
constructor(private winkelService: WinkelService){
this.selectedWinkel = {naam: ''}
}
onWinkelSelected(){
this.winkelSelected.emit(this.selectedWinkel);
}
}
Stores dropdown html:
<label for="winkelSelect">Kies winkel:</label>
<select id="winkelSelect" [(ngModel)]="selectedWinkel" (change)="onWinkelSelected()">
<option name="winkel" *ngFor="let winkel of winkels" [ngValue]="selectedWinkel" title="{{winkel.adres | titlecase}}, {{winkel.post}} {{winkel.gemeente}}">{{winkel.naam}}</option>
</select>
And finally, the second dropdown (vegetables):
export class GroentenComponent implements OnInit {
groentes: Groente[] = [];
@Output() groenteSelected = new EventEmitter<{naam:string, prijs:number}>();
constructor(private groenteService: GroenteService) {
this.selectedGroente = {naam: '', prijs: 0};
}
ngOnInit(): void {
this.getGroenten();
}
getGroenten(): void {
this.groenteService.getGroentes()
.subscribe(groentes => this.groentes = groentes);
}
selectedGroente: { naam: string, prijs: number }
onGroenteSelected(){
this.groenteSelected.emit(this.selectedGroente);
}
}
Vegetable dropdown html:
<label for="groenteSelect">Kies groente:</label>
<select id="groenteSelect" [(ngModel)]="selectedGroente" (change)="onGroenteSelected()">
<option *ngFor="let groente of groentes" name="groente" [ngValue]="selectedGroente">{{groente.naam}} ({{groente.prijs}}/{{groente.eenheid}})</option>
</select>
I’m guessing I messed up something with ngModel/ngValue? I’m totally new to Angular so I’m not sure if I misunderstood anything..
>Solution :
It looks like the issue is with how you are using [(ngModel)] and [ngValue] in your dropdowns.
In the WinkelsComponent, you are correctly using [ngValue] to bind the selected value to selectedWinkel. However, in the GroentenComponent, you are using [ngValue]="selectedGroente", which is binding the initial value of selectedGroente to each option. Instead, you should bind each option to the corresponding groente object using [ngValue]="groente".
Additionally, you are not setting the selectedWinkel and selectedGroente variables correctly in your components. You should set them to null or undefined instead of an empty object.
Here’s the updated code for GroentenComponent:
export class GroentenComponent implements OnInit {
groentes: Groente[] = [];
@Output() groenteSelected = new EventEmitter<{naam:string, prijs:number}>();
selectedGroente: { naam: string, prijs: number };
constructor(private groenteService: GroenteService) {}
ngOnInit(): void {
this.getGroenten();
}
getGroenten(): void {
this.groenteService.getGroentes()
.subscribe(groentes => this.groentes = groentes);
}
onGroenteSelected(){
this.groenteSelected.emit(this.selectedGroente);
}
}
And the updated HTML for GroentenComponent:
<label for="groenteSelect">Kies groente:</label>
<select id="groenteSelect" [(ngModel)]="selectedGroente" (change)="onGroenteSelected()">
<option *ngFor="let groente of groentes" [ngValue]="groente">{{groente.naam}} ({{groente.prijs}}/{{groente.eenheid}})</option>
</select>
Note that the same changes should be applied to selectedWinkel and the WinkelsComponent.