代码之家  ›  专栏  ›  技术社区  ›  Present practice

如何在ngFor中使用反应形式

  •  2
  • Present practice  · 技术社区  · 7 年前

    一个用户数组可以有多个元素(用户)。在模板中,我遍历这个数组并为每个元素添加一个表单。现在,每个表单都绑定到相同的表单组值。如果我为第一个用户填写表单,则所有表单的“提交”按钮都将启用。如何将每个窗体指向唯一的窗体组或唯一的变量?

    组成部分:

    import { FormControl, FormGroup, Validators, FormBuilder} from '@angular/forms';
    ...
    export class UserComponent implements OnInit {
     form: FormGroup;
     @input users: any[];
    
     constructor(private _fb: FormBuilder) {}
     ngOnInit() {
      this.form = this._fb.group({
       address: new FormControl('', [Validators.required]),
       phone: new FormControl('', [Validators.required]),
       });
     }
    
     add() {
       if (this.form.valid){
         // code
       }
     }
    

    模板:

     <div *ngFor="let user if users">
      {{user.name}}
        <form [formGroup]="form"  (ngSubmit)="add()">         
         <div class="form-group">
           <label>Address:</label>
           <input formControlName="address" class="form-control">
           <label>Phone:</label>
           <input formControlName="phone" class="form-control"></input>
         </div>
         <button type="submit" class="submit" [disabled]="!form.valid">Submit</button>    
        </form>
     </div>
    
    3 回复  |  直到 7 年前
        1
  •  3
  •   TanvirArjel    7 年前

    要解决你的问题你必须使用 formArray 具体如下:

    在组件中:

    export class UserComponent implements OnInit {
         usersForm: FormGroup;
         errorMessage : string;
    
         constructor(private formBuilder: FormBuilder) {}
    
          ngOnInit() {
              this.usersForm= this.formBuilder.group({
                   users: this.formBuilder.array([
                    this.formBuilder.group({
                      address: [null, [Validators.required]],
                      phone: [null, [Validators.required]]
                    })
                  ])
               });
           }
    
          initUserRow(): FormGroup {
                return this.formBuilder.group({
                   address: [null, [Validators.required]],
                   phone: [null, [Validators.required]],
            });
           }
    
           addUserRow(): void {
              const usersArray= 
                 <FormArray>this.usersForm.controls['users'];
               usersArray.push(this.initUserRow());
            }
    
           removeUserRow(rowIndex: number): void {
               const usersArray= <FormArray>this.usersForm.controls['users'];
               if (usersArray.length > 1) {
                  usersArray.removeAt(rowIndex);
               } else {
                this.errorMessage = 'You cannot delete this row! form should contain at least one row!';
               setTimeout(() => {
                 this.errorMessage = null;
               }, 4000);
             }
           }
    
     }
    

    在视图中:

    <form *ngIf="usersForm" [formGroup]="usersForm" (ngSubmit)="createUsers()">
        <table class="table table-sm table-bordered">
                <thead>
                  <tr class="text-center">
                    <th>Address</th>
                    <th>Phone</th>
                    <th>Action</th>
                  </tr>
                </thead>
                <tbody formArrayName="users">
                  <tr *ngFor="let item of usersForm.controls.users.controls; let $index=index" [formGroupName]="$index">
                    <td style="min-width: 120px">
                          <input class="form-control" type="text" formControlName="address"/>
                          <div class="text-danger" *ngIf="usersForm.controls['users'].controls[$index].controls['address'].touched
                             && usersForm.controls['users'].controls[$index].controls['address'].hasError('required')">
                            Please enter address!
                          </div>
                    </td>
    
                    <td style="min-width: 120px">
                          <input class="form-control" type="text" formControlName="address"/>
                          <div class="text-danger" *ngIf="usersForm.controls['users'].controls[$index].controls['phone'].touched
                             && usersForm.controls['users'].controls[$index].controls['phone'].hasError('required')">
                            Please enter phone number!
                          </div>
                    </td>
    
                    <td style="width: 100px">
                      <button (click)="addUserRow()" class="btn btn-success btn-sm mr-1" type="button"><i class="fa fa-plus"></i></button>
                      <button (click)="removeUserRow($index)" class="btn btn-danger btn-sm" type="button"><i class="fa fa-times"></i></button>
                    </td>
                  </tr>
                </tbody>
              </table>
    </form>
    

    希望你的问题现在能解决!

        2
  •  2
  •   DeborahK    7 年前

    对于反应式表单,可以定义数据结构以在代码中保存表单数据。在你的例子中,你用 this.form . 但是表单定义只有一个地址控件和一个电话控件。所以你告诉Angular只存储一个地址和一个电话。

    要允许多个地址/电话组,您需要@DavidZ提到的FormArray。顾名思义,form array允许您拥有一个表单值数组。

    在您的示例中,FormArray将由一个FormGroup组成,每个用户有一个条目。表单组将由一组表单控件组成:地址和电话。

    窗体组件

    这个例子有一个名称和一个地址数组,但是应该给你一个大致的概念:

    ngOnInit(): void {
        this.customerForm = this.fb.group({
            name: ['', [Validators.required, Validators.minLength(3)]],
            addresses: this.fb.array([this.buildAddress()])
        });
    }
    
    buildAddress(): FormGroup {
        return this.fb.group({
                addressType: 'home',
                street1: ['', Validators.required],
                street2: '',
                city: '',
                state: '',
                zip: ''
        });
    }
    

    您可以在此处找到完整的代码: https://github.com/DeborahK/Angular2-ReactiveForms/tree/master/Demo-Final-Updated

        3
  •  0
  •   DavidZ    7 年前

    你可以用 FormArray , this article 总结得很好。

    也要确保你明白 differences 之间 福尔马雷 FormGroup

    推荐文章