Home > Enterprise >  How to inicialize an array with values inside reactive form in Angular
How to inicialize an array with values inside reactive form in Angular

Time:11-11

I have this form which has an array called "channel". Everytime that I click on a button, addChanels() is called, and new group is added inside my array. It's working when I create a new registry. But when I need to edit this registry, I need that my form array already have value.

aplicativo = this.activatedRoute.snapshot.data['aplicativo'];

ngOnInit(): void {

    this.form = this._formBuilder?.group({
      id: [this.aplicativo.id],
      name: [this.aplicativo.name, Validators.required],
      version: [this.aplicativo.version, Validators.required],
      appId: [this.aplicativo.appId, Validators.required],
      channel: this._formBuilder?.array([this.aplicativo.channel]),
    });
  }

  get channel() {
    return this.form?.controls['channel'] as FormArray;
  }

  addChanels() {
    const channelArray = this._formBuilder?.group({
      canais: [],
      topicos: [],
    });

      this.channel.push(channelArray);
  }

but angular returns me the error

Cannot find control with path: 'channel -> 0 -> canais'

*html

<button type="button" mat-raised-button color="primary" (click)="addChanels()">Adicionar</button>

          <ng-container formArrayName="channel">
            <ng-container *ngFor="let chan of channel.controls; let i = index">

              <mat-card [formGroupName]="i" >
                <button type="button" mat-icon-button color="primary" >
                  <mat-icon  (click)="deleteChannels(i)">cancel</mat-icon>
                </button>

                <div >

                  <div >
                    <mat-form-field appearance="outline">
                      <mat-label>Canais</mat-label>
                      <input matInput formControlName="canais" />
                    </mat-form-field>
                  </div>

                  <div >
                    <mat-form-field appearance="outline">
                      <mat-label>Tópicos</mat-label>
                      <input matInput formControlName="topicos" />
                    </mat-form-field>
                  </div>
                </div>
              </mat-card>
            </ng-container>
          </ng-container>

Resolver:

 resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    if (route.params && route.params['id']) {
      return this.aplicativosService.togetAplicativoById(route.params['id']);
    }

    return of({});
  }

routing:

 {
    path: 'configurar-aplicativo',
    component: ConfiguracaoAplicativoComponent,
    resolve: {
      aplicativo: AplicativoResolverGuard,
    },
  },
  {
    path: 'editar-aplicativo/:id',
    component: ConfiguracaoAplicativoComponent,
    resolve: {
      aplicativo: AplicativoResolverGuard,
    },
  },

CodePudding user response:

I suggest you turn on strict mode, or something so that typescript can tell you in IDE what you are actually doing wrong.

You would have gotten an error when doing this:

channel: this._formBuilder?.array([this.aplicativo.channel]),

Something in the line that:

this.aplicativo.channel is missing the following properties from AbstractControl....

So what you need to actually do is to push formgroups into the array (AbstractControl is the base class, thus the error), you cannot just put a "regular" array in. So I suggest the following:

form!: FormGroup;

constructor(private _formBuilder: FormBuilder) { }

ngOnInit() {
  this.form = this._formBuilder.group({
    channel: this._formBuilder.array([])
  });
  this.build();
}

// add form controls
build() {
 // DON'T use "any", type your data, being lazy just for the sake of the demo...
 this.aplicativo?.channel.map((x: any) => {
   (this.form.get('channel') as FormArray).push(this._formBuilder.group({
     topicos: [x.topicos],
     canais: [x.canais]
   }))
 })
}

Now you are inserting formgroups into the formarray!

  • Related