zeuz1983
zeuz1983

Reputation: 123

Why mat-select clear the value in this reactive form?

I´m working on an app like google forms, we have a form with questions, we get these questions from an api and dynamically render the form. the problem is that when i want to add validation to the form with angular reactive forms, the mat-select stops working and every time i select a value, the select is clear.

I already try to adapt this https://medium.com/aubergine-solutions/add-push-and-remove-form-fields-dynamically-to-formarray-with-reactive-forms-in-angular-acf61b4a2afe with no luck

template

<mat-horizontal-stepper [linear]="true" #stepper style="background: transparent">
  <mat-step *ngFor="let materia of materias;let m = index;" [stepControl]="createForm(materia.id)">
    <ng-template matStepLabel>{{materia.descripcion}}</ng-template>
    <form [formGroup]="getForm(materia.id)">
      <div fxLayout="column" fxLayoutAlign="space-around stretch" fxLayoutGap="10px">
        <div>
          <mat-card *ngFor="let competencia of materia.competencias">
            <mat-card-header>
              <mat-card-title>{{competencia.nombre}}</mat-card-title>
            </mat-card-header>
            <mat-card-content>              
              <div fxLayout="column" fxLayoutGap="30px" formArrayName="{{createFormArray(materia.id,competencia.id)}}">
                <div fxLayout="row">
                  <i>{{competencia.descripcion}}</i>
                </div>
                <div fxLayout="column" fxLayoutGap="2px">
                  <span *ngFor="let competenciaSimple of competencia.competenciasSimples; let i = index;" fxLayout="row">
                    <mat-form-field appearance="outline"
                      *ngIf="competenciaSimple !== null && competenciaSimple !== undefined" fxFlex>
                      <mat-select (selectionChange)="onSelected($event,competenciaSimple)"
                        [value]="getSelectedValue(competenciaSimple)" [formControl]="createControl(materia.id,competencia.id)" [id]="i">
                        <span *ngFor="let fase of competenciaSimple.fases">
                          <mat-option *ngFor="let conductaObservable of fase.conductasObservables"
                            [value]="conductaObservable">
                            {{conductaObservable.descripcion}}
                          </mat-option>
                        </span>
                      </mat-select>
                    </mat-form-field>
                    <!-- <input type="hidden" value="competenciaSimple" [(ngModel)]="calificacion.conductasObservables[i].competenciaSimple"/> -->
                  </span>
                </div>
              </div>

            </mat-card-content>
          </mat-card>
        </div>
        <div fxLayout="row">
          <button mat-flat-button type="button" matStepperPrevious *ngIf="!isFirstPage" color="primary"
            fxFlex="20">ANTERIOR</button>
          <span fxFlex="80"></span>
          <button mat-flat-button type="button" *ngIf="!isLastPage" color="primary" fxFlex="20">SIGUIENTE</button>
          <button mat-flat-button type="button" (click)="onSubmit()" *ngIf="isLastPage" color="accent"
            fxFlex="20">TERMINAR</button>
        </div>
      </div>
    </form>
  </mat-step>
</mat-horizontal-stepper>

component.ts


forms = new Array<FormGroup>();

getForm(index: number): FormGroup {
    return this.forms[index];
  }

  createForm(index: number): FormGroup {
    const form = this.formBuilder.group({});
    this.forms[index] = form;
    return form;
  }

  createFormArray(index: number, name: string): string {
    const array = this.formBuilder.array([]);
    const arrayName = `competencia_${name}`;
    this.forms[index].addControl(arrayName, array);
    return arrayName;
  }

  createControl(index: number, arrayName: string): FormControl {
    const control = this.formBuilder.control(false);
    const an = `competencia_${arrayName}`;
    const array = (this.forms[index].get(an));
    (array as FormArray).push(control);
    return control;
  }

  getControlId(): string {
    this.controlNumber += 1;
    return this.controlNumber.toString()
  }

The idea is to validate the mat-select as required so the stepper cant advance when no value is selected, that works if a add the Validator, but the mat-select doesn´t persist the value so if i remove the [formControl]="createControl(materia.id,competencia.id)" the mat-select work but no validation result.

Upvotes: 0

Views: 805

Answers (1)

Robinyo
Robinyo

Reputation: 596

There are several popular open source Angular Form Libraries (you can take a look at the source code and see how they dynamically add validation's to a control):

Upvotes: 1

Related Questions