17

I have a Modal Form with the following code in the template markup

  <form [formGroup]="modalFG">
  ...
  <ion-item *ngIf="isChangeStatus()">
      <ion-select formControlName="jobStatus"
                  (ionChange)="jobStatusChangeHandler($event)">
        <ion-option value=4>Success</ion-option> 
        <ion-option value=5>Failure</ion-option>
        <ion-option value=6>Terminated</ion-option> 
        <ion-option value=8>Inactive</ion-option> 
      </ion-select>
  </ion-item>
  </form>

In the Typescript I've specified a value, but I can't get past this error.

Error: Must supply a value for form control with name: 'jobStatus'.

Can someone tell me what I'm doing wrong?

...
private modalFG:FormGroup;
private jobStatus:number;
constructor(
  private navParams:NavParams,
  private view:ViewController,
  private fb: FormBuilder,
  ...
) {
    this.changeStatus = false;
    this.modalFG = fb.group({
      comment: ['', Validators.required],
      jobStatus: this.jobStatus
    });
}
private ionViewWillLoad():void {
    const data = this.navParams.get('data');
    this.modalFG.setValue({'jobStatus': this.jobStatus});
}

private jobStatusChangeHandler(ev:any) {
    console.log(ev);
}

private isChangeStatus():boolean {
    return this.changeStatus;
}

I also have button handler for submit with this:

this.exitData.jobStatus = this.modalFG.get('jobStatus').value;
this.view.dismiss(this.exitData);

This is the full error message:

Error: Must supply a value for form control with name: 'jobStatus'.
    at http://localhost:8100/build/vendor.js:22102:23
    at http://localhost:8100/build/vendor.js:22026:66
    at Array.forEach (<anonymous>)
    at FormGroup._forEachChild (http://localhost:8100/build/vendor.js:22026:36)
    at FormGroup._checkAllValuesPresent (http://localhost:8100/build/vendor.js:22100:14)
    at FormGroup.setValue (http://localhost:8100/build/vendor.js:21907:14)
    at ModalPage.webpackJsonp.124.ModalPage.ionViewWillLoad (http://localhost:8100/build/main.js:648:22)
    at ModalImpl.ViewController._lifecycle (http://localhost:8100/build/vendor.js:17471:33)
    at ModalImpl.ViewController._willLoad (http://localhost:8100/build/vendor.js:17331:14)
    at OverlayPortal.NavControllerBase._willLoad (http://localhost:8100/build/vendor.js:44112:18)

Since it says ionViewWillLoad in the call stack, the error must be something in that section AFAIK!

JGFMK
  • 8,425
  • 4
  • 58
  • 92

6 Answers6

36

My problem was that I wasn't providing all form controll values. For example:

<div formGroupName="form">
    <input formControlName="first">
    <input formControlName="second">
</div>

In this case, if you try to use method setValue and do not provide all controll values, like this:

this.form.setValue({ second: "" });

it will throw an error.

Solution

Either use setValue and provide value for all form controls:

this.form.setValue({ first: "", second: "" });

or, if you really intend to set partial values, use patchValue method:

this.form.patchValue({ second: "" });
Arthur Silva
  • 878
  • 1
  • 10
  • 15
  • Hi @Arthur Silva. I'll be sure to take a look at this next time I do some Ionic work. Thanks – JGFMK Nov 09 '18 at 14:25
10

Right... I had a form that used to only have a single form control, called 'comment'.

When I added a second, conditional form element, the syntax you need to use changes for setValue...

I needed to modify it from something like this:

  this.modalFG.setValue({'comment': data.comment});
  this.modalFG.setValue({'jobStatus': 0});

to:

  this.modalFG.controls['jobStatus'].setValue(0);
  this.modalFG.controls['comment'].setValue(data.comment);

because I now had two fields on the form...

Then everything fell into place and the misleading message about not having supplied form field disappeared.

I hate the syntax of Angular here, changing it's functioning behaviour when you go from 1 to n values!

JGFMK
  • 8,425
  • 4
  • 58
  • 92
  • Not necessarily, you should have been able to do just: this.modalFG.setValue({ 'comment': data.comment, 'jobStatus': 0 }); – jdobry Feb 12 '18 at 23:44
4

You could also use patchValue to just set one or more inputs individually:

this.form.patchValue({ first: "whatever" });
Terje Nesthus
  • 810
  • 3
  • 12
  • 30
1

"Must provide" tells you to pass a value to object on the Form. Ex:

Imaginate this scenario:

  public form = this.fb.group({
    production: this.fb.group({
      name: [''],
      id: [''],
      screenName: [''],
    })
  });

When you receive this data from server, the form wait 3 objects... "name", "id" and "screenName". And PatchValue works fine.

But, if you received data, you only have 2 objects: "name" and "screen name", and you try to do:

const formProduction = this.form.get('production');
formProduction.patchValue(this.yourData);

You can receive this message about "Must Apply", because the form wait all data. This happen to, if you force a Cast, like this:

const formProduction = this.form.get('production');
formProduction.patchValue(this.yourData as YourObject);

In this case in top of discuss, private jobStatus:number causes the same error.

A easy way to fix it is casting as unknown: If you server don't send all info, angular put in form only infos received, and ignore other fields.

const formProduction = this.form.get('production');
formProduction.patchValue(this.yourData as unknown);

;-)

0

Here

private jobStatus:number;

jobStatus value is 'undefined'.

Set a value:

private jobStatus:number = 0;

to make it work.

Vega
  • 27,856
  • 27
  • 95
  • 103
  • I've actually tried the code without even having jobStatus as class property, and use a literal like 0 on the fb.group statements, and in the set/get's. So I don't think even that will solve it. Have tried removing *ngIf Condition, making values on ion-option quoted the works... Nothing seems to prevent the message Must supply a value for form control with name: 'jobStatus'. – JGFMK Nov 11 '17 at 09:52
0

If you have to set only one ctrl value in the form group you should use

this.formGroup.patchValue({}),

If you have to set all ctrl value in the form group you should use

this.formGroup.setValue({}),

Viplav Soni
  • 1,489
  • 13
  • 18