6

I want to build a form in Ionic 2 in which I want to display a list of toggle (each toggle represents a sport).

The sport list being retrieved from DB I was trying to initialize my form within the subscribe() function but it looks like the view is throwing an error because at the time the [formGroup] attribute is parsed, the form doesn't exist yet...

In my view

<form [formGroup]="accountForm">

    <ion-list>

      <!-- Personal info -->
      <ion-list-header padding-top>
        Informations personnelles
      </ion-list-header>
      <ion-item>
        <ion-label stacked>Prénom</ion-label>
        <ion-input formControlName="firstname" [value]="(user | async)?.info.firstname" type="text"></ion-input>
      </ion-item>

      <!-- Sport info -->
      <ion-list-header padding-top>
        Mes préférences sportives
      </ion-list-header>
      <ion-list formArrayName="sports">

        <ion-item *ngFor="let sport of accountForm.controls.sports.controls; let i = index" [formGroupName]="i">
          <ion-label>{{sport.name | hashtag}}</ion-label>
          <ion-toggle formControlName="{{sport.name}}"></ion-toggle>
        </ion-item>

      </ion-list>

    </ion-list>


  </form>

In my controller

ionViewDidLoad() {
    console.log('MyAccountPage#ionViewDidLoad');

    // Retrieve the whole sport list
    this.sportList$ = this.dbService.getSportList();
    this.sportList$.subscribe(list => {

      // Build form
      let sportFormArr: FormArray = new FormArray([]);

      for (let i=0; i < list.length; i++) {
        let fg = new FormGroup({});
        fg.addControl(list[i].id, new FormControl(false));
        sportFormArr.push(fg);
      }

      this.accountForm = this.formBuilder.group({
        firstname: ['', Validators.compose([Validators.maxLength(30), Validators.pattern('[a-zA-Z ]*'), Validators.required])],
        company: [''],
        sports: sportFormArr
      });

      console.log('form ', this.accountForm);
    })
    // Toggled sports already registered to by user

  }

I tried to create the form within the constructor() and use addControl() to add the sport FormArray afterward. This solves the [formGroup] error (of course) but generates a new error regarding the "sports" control not being instantiated (not yet I guess).

Any idea?

5
  • 1
    either build an empty form initially and then patch the value. Or use a boolean flag to not show form until form has been built :) Commented Jun 1, 2017 at 9:07
  • Thanks @AJT_82 for your answer! I understand the flag solution but I am not sure that I understand the empty form solution. Would I get an error when the view will parse the different controls? Commented Jun 1, 2017 at 11:04
  • 1
    Well, the boolean flag is a wise solution if you know for sure data is coming, and you don't need to show a form initially, empty or not. What I mean with "empty form" is simply that you build an empty form with the same structure you have currently, you just don't set any values. Then there will not be an error thrown since there are no values to be set, the form is just empty. But as said, you can use boolean flag if you know data is coming and you don't need to show a form if there is no data coming. Commented Jun 1, 2017 at 11:28
  • 1
    And with patching value, I mean you could use patchValue function, which is available for formgroup. to set the values to the form once you have received the data. Commented Jun 1, 2017 at 11:29
  • 1
    Perfect, Thanks again @AJT_82! Commented Jun 1, 2017 at 12:07

1 Answer 1

21

Use an *ngIf condition to do a boolean check and load the view accordingly.

<form *ngIf="accountForm" [formGroup]="accountForm">

    <ion-list>

      <!-- Personal info -->
      <ion-list-header padding-top>
        Informations personnelles
      </ion-list-header>
      <ion-item>
        <ion-label stacked>Prénom</ion-label>
        <ion-input formControlName="firstname" [value]="(user | async)?.info.firstname" type="text"></ion-input>
      </ion-item>

      <!-- Sport info -->
      <ion-list-header padding-top>
        Mes préférences sportives
      </ion-list-header>
      <ion-list formArrayName="sports">

        <ion-item *ngFor="let sport of accountForm.controls.sports.controls; let i = index" [formGroupName]="i">
          <ion-label>{{sport.name | hashtag}}</ion-label>
          <ion-toggle formControlName="{{sport.name}}"></ion-toggle>
        </ion-item>

      </ion-list>

    </ion-list>


  </form>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.