claudiomatiasrg
claudiomatiasrg

Reputation: 618

Readonly/Disabled input not submitting in Angular

I've been having problems creating a form in Angular 2. I need to submit some values that are dinamically generated by a service. Using the http module of Angular I get a price and then the user can now exactly how much bitcoin is an X amount of chilean pesos. What I'm trying to do is submit all that data. I can't do it because angular forms are not submitting the disabled/readonly inputs. These inputs are the exchange rate and the target amount (equivalent in btc).

I tried the template driven approach and the data driven approach with no success. I can't even log the values in the console. If I remove disabled or readonly property from the inputs the values are logged in the console and submitted to my database.

Thanks for taking the time to help me. This is my code:

component.ts

import { Component, OnInit } from '@angular/core';
import { SurbtcService } from '../services/exchange/surbtc.service';
import { FormBuilder, FormGroup, Validators, FormControl, NgForm } from "@angular/forms";
import { FiredbService } from '../services/firedb.service';
import * as firebase from 'firebase/app';

@Component({
  selector: 'my-dashboard',
  templateUrl: './dashboard.component.html'
})
export class DashboardComponent {

  //myForm2: FormGroup;
  //error = false;
  //errorMessage = '';

  constructor(private surbtcService: SurbtcService, private fb: FormBuilder, private dbfr: FiredbService) {
/*
          this.myForm2 = this.fb.group({
            email: ['', Validators.email],
      clpmount: ['', Validators.required],
      btcmount: [''],
      rate: [''],
      descripcion: ['']

        });
 */  }
//Form

info = {
  rate: '',
  btcmount: ''
};


onSub() {
 console.log(this.info);
  }



  //surbtcservice

  prices: any;
  baseAmount: 1;

  get exchangeRate() {
   return this.prices * 0.989
    }

  get targetAmount() {
   return this.baseAmount / this.exchangeRate;
    }

  ngOnInit() {
     this.surbtcService.getPrices()
      .subscribe(prices => {
       this.prices = prices.ticker.min_ask[0];
       console.log(prices.ticker.min_ask[0]);
        });
    } }

As you can see in my code, the data driven approach is commented except for the function used to submit the form.

html:

<form (ngSubmit)="onSub(f)" #f="ngForm">
          <div class="form-group">
            <md-input-container class="full-width">
              <input mdInput type="number" id="montoclp" name="clpmount" placeholder="Ingrese el monto en CLP" [(ngModel)]="baseAmount" name="clp">
            </md-input-container>
            <md-input-container class="full-width">
              <input mdInput class="form-control" name="btcmount" [ngModel]="info.btcmount" placeholder="Monto en BTC" id="vat" [value]="targetAmount | number:'1.8-8'" readonly>
            </md-input-container>
            <md-input-container class="full-width">
              <input mdInput class="form-control" name="rate" [ngModel]="info.rate" placeholder="Tasa de cambio" id="street" [value]="exchangeRate | number:'1.0-0'" readonly>
            </md-input-container>
            <md-input-container class="full-width">
              <input mdInput type="mail" class="form-control" ngModel name="email" placeholder="E-mail cliente (Opcional)">
            </md-input-container>
            <md-input-container class="full-width">
              <input mdInput type="text" class="form-control" ngModel name="descripcion" placeholder="Descripción pago (Opciona)">
            </md-input-container>
          </div>
          <button md-raised-button type="submit" color="primary" class="btn-w-md">Confirmar</button><div class="divider divider-sm"></div>
        </form>

Thanks again!

EDIT!!!:

data driven html:

            <form [formGroup]="myForm2" (ngSubmit)="onSub()">
              <div class="form-group">
                <md-input-container class="full-width">
                  <input mdInput type="number" id="montoclp" name="clpmount" placeholder="Ingrese el monto en CLP" formControlName="clpmount" [(ngModel)]="baseAmount">
                </md-input-container>
                <md-input-container class="full-width">
                  <input mdInput class="form-control" name="btcmount" placeholder="Monto en BTC" formControlName="btcmount" [value]="targetAmount | number:'1.8-8'">
                </md-input-container>
                <md-input-container class="full-width">
                  <input mdInput class="form-control" name="rate" formControlName="rate" placeholder="Tasa de cambio" [value]="exchangeRate | number:'1.0-0'">
                </md-input-container>
                <md-input-container class="full-width">
                  <input mdInput type="mail" class="form-control" formControlName="email" name="email" placeholder="E-mail cliente (Opcional)">
                </md-input-container>
                <md-input-container class="full-width">
                  <input mdInput type="text" class="form-control" formControlName="descripcion" name="descripcion" placeholder="Descripción pago (Opciona)">
                </md-input-container>
              </div>
              <button md-raised-button type="submit" color="primary" class="btn-w-md">Confirmar</button><div class="divider divider-sm"></div>
            </form>

Upvotes: 5

Views: 12119

Answers (3)

AVJT82
AVJT82

Reputation: 73357

You can use getRawValue(), which gives you all form values, even the disabled ones.

So when your form looks something like this:

this.myForm2 = this.fb.group({
  email: ['', Validators.email],
  clpmount: ['', Validators.required],
  btcmount: [{value: '', disabled: true}],
  ....
});

using

this.myForm2.getRawValue()

will include in above example btcmount value.

EDIT:

Seeing the template... In reactive forms, Angular disregards value and [value]. We can overcome this and use one-way binding, which I also suggest you do with your field clpAmount and set [ngModel]="baseAmount". Why? Well, first of all the ngModel directive isn't even included in ReactiveFormsModule, so from that, even not clearly mentioned in docs, we can all but assume they should not be used together. We can also understand it, if using [(ngModel)] together, we would have two bidirectional bindings, which can sometimes cause issues.

[ngModel] is better, since Angular just binds the value from TS to template, and doesn't really care what happens next. In some cases, [ngModel] can be useful in reactive forms, this is one of those cases. Even though reactive forms ignore value, it does not ignore ngModel, so we can use that just fine here! So exchange [value] with [ngModel]:

<input mdInput  formControlName="btcmount" [ngModel]="targetAmount | number:'1.8-8'">

<input mdInput formControlName="rate" placeholder="Tasa de cambio" [ngModel]="exchangeRate | number:'1.0-0'">

Now you have all values when you use getRawValue() :)

Upvotes: 25

yusijs
yusijs

Reputation: 867

To expand on Vivek's ansver, with a reactive form, you would do it like this:

this.myForm2 = this.fb.group({
      email: ['', Validators.email],
      clpmount: ['', Validators.required],
      btcmount: [''],
      rate: [''],
      descripcion: ['']

});

and

public onSub() {
  console.log(this.myForm2.value);
}

or (on changes):

ngOnInit() {
  ...
  this.form.valueChanges.subscribe(value => console.log(value));
}

basically you want to grab the data from the actual form, and not from your model. Same thing goes for model driven, as Vivek outlined (pass in the form instead of using the model)

Upvotes: 1

Vivek Doshi
Vivek Doshi

Reputation: 58573

If you want all the form values then

Change this function

onSub() {
 console.log(this.info);
}

With

import { NgForm } from '@angular/forms';

onSub(formData : NgForm) {
 console.log(formData.value);
}

Readonly/Disabled input not submitting in Angular

Disabled will never be submitted in any form But Readonly , you will always get that in submitted form ,

Issue is with your code not with the angular

Upvotes: 1

Related Questions