Angular cast select value to int
FormsAngularCastingForms Problem Overview
I have a form with different selects like :
<select [(ngModel)]="selected.isConnected" (ngModelChange)="formChanged()" name="etat" id="etat" class="form-control">
<option value="0">Not connected</option>
<option value="1">Connected</option>
</select>
My backend expect to receive an int in the "isConnected" attribute. Unfortunately as soon as I change the value of the select the attribute is cast to a string :
{
isConnected : "0", // 0 expected
}
For standard <input>
I could use type="number"
but for a <select>
I'm clueless.
Is there a way to force angular 2 to cast the data to int ?
Forms Solutions
Solution 1 - Forms
Use [ngValue] instead of "value":
<select [(ngModel)]="selected.isConnected" id="etat">
<option [ngValue]="0">Not connected</option>
<option [ngValue]="1">Connected</option>
</select>
Solution 2 - Forms
If you want cast it within formChanged() method (Which you haven't provided yet). You should use + symbol as shown below,
formChanged(): void {
selected.isConnected = +selected.isConnected;
...
}
Solution 3 - Forms
No, sadly you're forced to parse it on your own in the formChanged()
method, since you always get a string back from the select
.
You could try it with something like this:
formChanged(): void {
selected.isConnected = parseInt(selected.isConnected);
// ...
}
Solution 4 - Forms
You can send a Number variable to select and assign the value for that select element. Then if you want to capture the value when it changes, you can add (change) event to select and retrieve the value as shown below.
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `<select value="{{isConnected}}" (change)="printConnected($event.target.value)" name="etat" id="etat" class="form-control">
<option value="0">Not connected</option>
<option value="1">Connected</option>
</select>
<div *ngIf="changed">You've selected {{isConnected}}<div>`
})
export class AppComponent {
isConnected : number = 1;
changed : boolean = false;
printConnected(value){
this.isConnected = value;
this.changed=true;
}
}
You can view an example at http://plnkr.co/edit/xO2mrTdpTGufkgXqdhYD?p=preview
Solution 5 - Forms
I am using reactive bindings and do not want to use [(ngModel)]
. Instead I created a piped observable that uses JSON.parse(value)
(because +value
doesn't handle "null"
):
*.component.html:
<div class="col-lg-4 form-group">
<label>Group Type</label>
<select class="form-control" (change)="groupType$.next($event.target.value)">
<option [value]="null"></option>
<option *ngFor="let groupType of filterData.groupTypes" [value]="groupType.id">{{groupType.label}}</option>
</select>
</div>
<div class="col-lg-4 form-group" *ngIf="filteredGroups$ | async as groupOptions">
<label>Group</label>
<select class="form-control" (change)="group$.next($event.target.value)">
<option [value]="null"></option>
<option *ngFor="let group of groupOptions" [value]="group.id">{{group.label}}</option>
</select>
</div>
<div class="col-lg-4 form-group">
<label>Status</label>
<select class="form-control" (change)="status$.next($event.target.value)">
<option [value]="null"></option>
<option *ngFor="let status of filterData.statuses" [value]="status.id">{{status.label}}</option>
</select>
</div>
*.component.ts:
group$ = new BehaviorSubject<string>(null);
groupId$ = this.group$.pipe(
map((groupId: string) => JSON.parse(groupId) as number)
);
groupType$ = new BehaviorSubject<string>(null);
groupTypeId$ = this.groupType$.pipe(
map((typeId: string) => JSON.parse(typeId) as number)
);
status$ = new BehaviorSubject<string>(null);
statusId$ = this.status$.pipe(
map((statusId: string) => JSON.parse(statusId) as number)
);
Solution 6 - Forms
[ngValue] is intended for objects. It generates an artificial option value even for numeric constants. For those who might be concerned about tests or readability, you can expand two way binding microsyntax
<select [ngModel]="selected.isConnected"
(ngModelChange)="selected.isConnected=$event && +$event" id="etat">
<option value="0">Not connected</option>
<option value="1">Connected</option>
</select>