Angular cast select value to int

FormsAngularCasting

Forms 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> 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongrunkView Question on Stackoverflow
Solution 1 - FormsAnthony BrenelièreView Answer on Stackoverflow
Solution 2 - FormsmicronyksView Answer on Stackoverflow
Solution 3 - FormsrinukkusuView Answer on Stackoverflow
Solution 4 - FormsGaryView Answer on Stackoverflow
Solution 5 - FormsR. SalisburyView Answer on Stackoverflow
Solution 6 - FormsStanislav ŠolcView Answer on Stackoverflow