ktsangop
ktsangop

Reputation: 1173

Is there a way to create a 'number' input FormControl in Angular 2 Reactive Forms

I have edited the official Angular.io tutorial on Dynamic Forms, in order to add a form control/input field of type "number".

https://plnkr.co/edit/NslBCrFZLQnLblAqcmzV

NumberQuestion class

import { QuestionBase } from './question-base';

export class NumberQuestion extends QuestionBase<string> {
  controlType = 'numberbox';
  type: string;

  constructor(options: {} = {}) {
    super(options);
    this.type = options['type'] || '';

  }
}

Creating a new NumberQuestion :

  //...
  new NumberQuestion({
    key: 'years',
    label : 'Years active',
    type : 'number',
    order : 4

  })

Template :

<div [formGroup]="form">
  <label [attr.for]="question.key">{{question.label}}</label>

  <div [ngSwitch]="question.controlType">

    <input *ngSwitchCase="'textbox'" [formControlName]="question.key"
            [id]="question.key" [type]="question.type">

    <input *ngSwitchCase="'numberbox'" [formControlName]="question.key"
            [id]="question.key" [type]="question.type">

    <select [id]="question.key" *ngSwitchCase="'dropdown'" [formControlName]="question.key">
      <option *ngFor="let opt of question.options" [value]="opt.key">{{opt.value}}</option>
    </select>

  </div> 

  <div class="errorMessage" *ngIf="!isValid">{{question.label}} is required</div>
</div>

If you click on the Load Defaults button, and then the Save button you will see that the form's value object, preserves the numeric type of the formControl 'Years active'.

But if you firstly type inside the 'Years active' control and then hit Save, you will see that the value has been transformed to string.

I understand that this is normal behavior, as described here : https://stackoverflow.com/a/35791893/2025271

I would like to know if there is a way to instruct Angular's FormControl to preserve number type inputs as "numbers", when accessing their value.

I know that i can do this manually, by using parseInt() to edit value on change, but i am trying to find if there is a built in way to do it.

Upvotes: 8

Views: 33298

Answers (2)

Lasithds
Lasithds

Reputation: 2291

I manage to fix it by prefixing form value with a plus sign and assign to a temporary variable.

let myNumber : number = + this.form.value.myNumber;

Upvotes: 3

Mohamed Ali RACHID
Mohamed Ali RACHID

Reputation: 3297

as an alternative dynamic solution to your question :

  • you can create an object that will contains the value of your form i called it myObject in the code
  • in submit you call the method createMyObject() that fetchs your questions one by one
  • then checks if its type of the is number :
    • if it's an number you add a number property to the object , where the key is the key of the question and the value of it is the value of the formControl , then add the property to myObject
    • else you create a string property and add it to myObject

Ts Code of DynamicFormComponent:

import { Component, Input, OnInit }  from '@angular/core';
import { FormGroup }                 from '@angular/forms';

import { QuestionBase }              from './question-base';
import { QuestionControlService }    from './question-control.service';

@Component({
  selector: 'app-dynamic-form',
  templateUrl: './dynamic-form.component.html',
  providers: [ QuestionControlService ]
})
export class DynamicFormComponent implements OnInit {

  @Input() questions: QuestionBase<any>[] = [];
  form: FormGroup;
  payLoad = '';
  myObject : any = {};

  createMyObject(){
    for(let question of this.questions){
      let key = question.key;
      if(question.type === "number"){
        let tempObj : number = +this.form.value[key];
        this.myObject[key] = tempObj;
      }
      else{
        let tempObj : string = this.form.value[key];
        this.myObject[key] = tempObj;
      }
    }
  }

  constructor(private qcs: QuestionControlService) {  }

  ngOnInit() {
    this.form = this.qcs.toFormGroup(this.questions);
  }

  onSubmit() {
    this.payLoad = JSON.stringify(this.form.value);
    this.createMyObject();
  }

  load(){
    this.form.patchValue({"firstName":"kratos","emailAddress":"[email protected]","brave":"solid","years":132});
  }
}


/*
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/

Html Code DynamicFormComponent :

<div>
  <button type="button" (click)="load()">Load Defaults</button>

  <form (ngSubmit)="onSubmit()" [formGroup]="form">

    <div *ngFor="let question of questions" class="form-row">
      <app-question [question]="question" [form]="form"></app-question>
    </div>

    <div class="form-row">
      <button type="submit" [disabled]="!form.valid">Save</button>
    </div>
  </form>

  <div *ngIf="payLoad" class="form-row">
    <strong>Saved the following values</strong><br>{{payLoad}}
  </div>

  <div *ngIf="payLoad" class="form-row">
    <strong>Saved the following values</strong><br>{{myObject | json}}
  </div>
</div>

Hope this will help :)

Upvotes: 0

Related Questions