在相对形式中使用formArray时出现“ TypeError:无法读取未定义的属性'控件'”

时间:2019-09-13 07:53:22

标签: javascript angular typescript

我正在使用formArray创建动态表单。但是我遇到了 “ TypeError:无法读取未定义的属性'控件'”

enter code here
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, FormArray } from '@angular/forms';
@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
 export class AppComponent implements OnInit {
 title = 'Trainner Registration Form ';
 registrationForm: FormGroup;

 get LanguagesForm() {
    return this.registrationForm.get('Languages') as FormArray;
 }

 addLanguage() {
  this.LanguagesForm.push(this.fb.control(''));
}


 constructor(private  fb : FormBuilder ) {}
   ngOnInit(){
     this.registrationForm = this.fb.group({
      personalDetails : this.fb.group({
      name: this.fb.group({
        firstName: [''],
        lastName: ['']
      }),
      aboutYours: [''],
      dob: [''],
      // lang: [''],
      Languages: this.fb.array([]),
      wTT: ['']
    })
  });

}


onSubmit() {
  console.log(this.registrationForm.value);
  // this._registerationservice.register(this.registrationForm.value).subscribe(
  //   response => console.log('Success', response),
  //   error => console.log('Error',error)
  // );
}

}

预期结果:如果用户单击“添加语言”按钮,则应创建一个新的输入字段。

实际结果:我收到“ TypeError:无法读取未定义的属性'controls'”

app.component.html文件

<div style="text-align:center">
<h1>Welcome to {{ title }}!</h1>
</div>

<mat-horizontal-stepper >

  <mat-step  [stepControl]="personalDetails">
    <ng-template matStepLabel>Enter Personal Details</ng-template>
    <div formGroupName="personalDetails">
      <div formGroupName="name">
          <div class="form-group">
            <label>First Name : </label>
            <input type="text"  formControlName="firstName" class="form-control"  >
          </div>

          <div class="form-group">
            <label>Last Name : </label>
            <input type="text" formControlName="lastName" class="form-control">
          </div>
      </div>    
      <div class="form-group">
          <label>DOB : </label>
          <input type="date" formControlName="dob" class="form-control">
        </div>

        <div class="form-group">
          <label>About Yourself : </label>
          <textarea formControlName="aboutYours" class="form-control"></textarea>
        </div>

        <div class="form-group">
            <label>Language(s) : </label>
            <button type="button" class="btn btn-secondary btn-sm m-2" (click)="addLanguage()">Add Language</button>
            <!-- <input type="text" formControlName="lang" class="form-control"> -->

            <div formArrayName="Languages">
                <div *ngFor="let lang of langsform.controls; let i =index;">
                    <input type="text" class="form-control" [formControlName]="i">
                </div>
              </div>

          </div>


</mat-horizontal-stepper>
</form>
</div>

4 个答案:

答案 0 :(得分:1)

我认为问题在于您在onInit内初始化了registrationForm对象,并且此时模板已被解析,因此您应该在此div ViewModelProvider(context as YourActivity)[ViewModel::class.java]上添加一个*ngIf="this.registrationForm"

答案 1 :(得分:1)

之所以会发生这种情况,是因为您没有将personalDetails设置为较高的formGroup,因此,在Languages中名称为registrationForm的控件看起来像是Languages的控制者。是personalDetails表单组中的控件,与LanguagesForm.controls相关的错别字必须是'Languages.controls'

<div class="form-group">
  <label>Language(s) : </label>
  <button type="button" class="btn btn-secondary btn-sm m-2" (click)="addLanguage()">Add Language</button>

  <div [formGroup]="registrationForm"> <!-- ? -->
    <div [formGroupName]="'personalDetails'"> <!-- ? -->

      <div formArrayName="Languages">
        <div *ngFor="let lag of registrationForm.get('personalDetails').get('Languages').controls; let i =index;">
          <input type="text" class="form-control" [formControlName]="i">
        </div>

      </div>
    </div>
  </div>
</div>

您可以使用get属性来访问语言表单

  langsform() :FormArray { 
    return this.registrationForm.get('personalDetails').get('Languages') as FormArray 
  }

模板

<div [formGroup]="registrationForm">
  <div [formGroupName]="'personalDetails'">

    <div formArrayName="Languages">
      <div *ngFor="let lang of langsform.controls; let i =index;">
          <input type="text" class="form-control" [formControlName]="i">
      </div>
    </div>
  </div>
</div>

demo ??

答案 2 :(得分:1)

您将FormArray命名为“ Languages”,而不是LanguagesForm。

<div *ngFor="let Languages of registrationForm.controls.personalDetails.controls.Languages.controls; let i =index;">
      <input type="text" class="form-control" [formControlName]="i">
</div>

编辑: 我更改了getLangsform和<mat-step><form>标签。 https://stackblitz.com/edit/angular-lc8mu1

答案 3 :(得分:1)

尝试这种方式:

在您的HTML中:

 <div class="form-group">
      <div formArrayName="languages">
        <label>Languages</label>

        <div class="row">
          <div class="col-8">
            <input type="text" class="form-control" id="languages">
          </div>
          <div class="col-4">
            <button type="button" class="btn btn-primary" (click)="onAddLanguages()">Add</button>
          </div>
        </div>

        <div class="form-group row" *ngFor="let languages of registrationForm.get('languages').controls; let i = index">
          <div class="col-8">
            <input type="text" class="form-control" [formControlName]="i">
          </div>
          <div class="col-4">
            <button type="button" class="btn btn-danger" (click)="onDeleteLanguages(i)">Delete</button>
          </div>
        </div>
      </div>
    </div>

在您的TS中:

this.registrationForm = new FormGroup({
       'languages': new FormArray([])
});
onAddLanguages() {
const control = new FormControl(null, Validators.required);
(<FormArray>this.registrationForm.get('languages')).push(control)
}
onDeleteLanguages(index) {
(<FormArray>this.registrationForm.get('languages')).removeAt(index)
}