【问题标题】:Angular2 Reactive Form TableAngular2反应形式表
【发布时间】:2017-12-22 15:11:19
【问题描述】:

我在查找和尝试做我想做的事情时遇到了一些麻烦。

我有一个表,每行都有输入,我希望使用 ngFor 创建的每一行都被视为一个表单组。

在每个表单组中,我想要验证,如果在行中填充了任何控件,则需要在完成提交之前填充整个表单组。

这是我目前模板中的内容。

我在组件中还没有任何东西,因为 Angular.io 并且搜索了几个小时并没有显示任何接近我想要的东西。

<form>
        <table id="table" class="mdl-data-table mdl-js-data-table mdl-data-table mdl-shadow--2dp">
            <thead>
                <tr>
                    <th>Day</th>
                    <th>Description</th>
                    <th>Open Time</th>
                    <th>Close Time</th>
                </tr>
            </thead>

            <tbody>

                <tr *ngFor="let scheduleDetail of scheduleDetails">
                    <td style="padding: 0 8px 0 8px;">{{weekdayConverter(scheduleDetail.dayId)}}</td>
                    <td class="pad-input">
                        <mdl-textfield style="max-width:100px;" type="text" class="font" name="description" [(ngModel)]="scheduleDetail.description"></mdl-textfield>
                    </td>
                    <td>
                        <mdl-textfield style="max-width:75px" type="text" error-msg="hh:mm" name="openTime" pattern="([01]\d|2[0-3]):?([0-5]\d)" [(ngModel)]="scheduleDetail.openTime"></mdl-textfield>
                    </td>
                    <td>
                        <mdl-textfield style="max-width:75px" type="text" error-msg="hh:mm" name="closeTime" pattern="([01]\d|2[0-3]):?([0-5]\d)" [(ngModel)]="scheduleDetail.closeTime"></mdl-textfield>
                    </td>
                </tr>

            </tbody>

        </table>
    </form>

更新

在模板中添加了以下内容:

将输入更改为:

<mdl-textfield (keyup)="formChange(scheduleDetail)" style="max-width:100px;" type="text" class="font" name="description" [(ngModel)]="scheduleDetail.description"></mdl-textfield>

在组件中添加了以下内容:

    formChange(detail:scheduleDetail){
if(this.checkValid(detail)==false)
this.scheduleDetails.filter(detail => detail == detail)[0].require=true;
else
this.scheduleDetails.filter(detail => detail == detail)[0].require=false;

this.checkForm();
}

checkValid(detail:scheduleDetail){
if(detail.description!=null && detail.description!=""){
  if(this.checkTime(detail))
    return true
  else 
    return false
}
else
  return true
}

checkTime(detail:scheduleDetail){
  if(
    (detail.openTime!=null && detail.closeTime!=null) && 
    ( detail.openTime!="" && detail.closeTime!="") &&
    (this.checkRegExp(detail.openTime) && this.checkRegExp(detail.closeTime))
    ){
    return true
    }

  else if((this.checkRegExp(detail.openTime) && this.checkRegExp(detail.closeTime))){
    return true
  }
  else return false
}

checkRegExp(time:string){
let timeRegExp = /([01]\d|2[0-3]):?([0-5]\d)/;

if(timeRegExp.test(time)){
  return true;
}
else
  return false;

}

checkForm(){
let valid: boolean = true;
  this.scheduleDetails.forEach(detail => {
    if(detail.require==true){
      valid = false;
    }
  });

    this.scheduleDetails.forEach(detail => {
    if(detail.description=="" || detail.description==null){
      valid = false;
    }
  });
this.formValid = valid;
}

【问题讨论】:

    标签: forms angular html-table controls


    【解决方案1】:

    模型驱动的表单

    您使用的是模板驱动的表单,难以扩展和维护。

    在这里,我将指导您迁移到模型驱动的表单。

    组件

    export class WeekScheduleComponent {
    
    // Our empty Form
    myForm: FormGroup;
    
    constructor(private fb: FormBuilder){
     // We inject FormBuilder to our component
    
     // Now, we instantiate myForm with FormBuilder
     // Notice that myForm is a FormGroup which contains an empty FormArray
        this.myForm = this.fb.group({
                       scheduleDetail: this.fb.array([])
                      })
    }
    
    addRow(){
        // This function instantiates a FormGroup for each day
        // and pushes it to our FormArray
    
        // We get our FormArray
        const control = <FormArray>this.myForm.controls['scheduleDetail'];
    
        // instantiate a new day FormGroup;
        newDayGroup: FormGroup = this.initItems();
    
        // Add it to our formArray
        control.push(newDayGroup);
    }
    
    initItems(): FormGroup{
        // Here, we make the form for each day
    
        return this.fb.group({
                   description: [null, Validators.required],
                   openTime: [null, Validators.required],
                   closeTime: [null, Validators.required]
               });
    }
    
    submit(){
        // do stuff and submit result
        console.log(this.myForm.value);
    }
    }
    

    在您的模板中:

    <form [formGroup]="myForm" *ngIf="myForm">
         <table formArrayName="scheduleDetail">
    
                <tr *ngFor="let item of myForm.controls.scheduleDetail.controls; let i=index"
                    [formGroupName]="i" >
    
                    <td><input type='text' formControlName="description"></td>
                    <td><input type='text' formControlName="openTime"></td>
                    <td><input type='text' formControlName="closeTime"></td>
    
                </tr>
    
         </table>
    </form>
    
    <button (click)="addRow()">Add new item</button>
    <button (click)="submit()" [disabled]="!myForm.valid">Submit</button>
    

    【讨论】:

    • 我很难遵循这个。我的表将包含 7 行,一周中的每一天都有 1 行。当我尝试适应和理解时,您在 ngFor 中的部分让我感到困惑。所以每个 tr 都可以充当一个表单组,并且为它动态保留一个表单组变量,以便我可以引用其中的控件。我想我在这里有点过头了....
    • 不,实际上并不难。但我会更详细地更新,以便您理解代码。你知道,我需要睡一会儿。现在是凌晨 5 点。在这里。
    • 我最终只是将很多 if 与我的所有验证链接在一起,并得到了相同的结果。用我所做的更新帖子,以防将来对某人有所帮助。
    【解决方案2】:

    组件

    import { Component, OnInit } from '@angular/core';
    import {FormGroup, FormBuilder, FormControl, Validators, FormArray} from '@angular/forms';
    
    @Component({
      selector: 'app-sales',
      templateUrl: './sales.component.html',
      styleUrls: ['./sales.component.css']
    })
    export class SalesComponent implements OnInit {
    
      myForm: FormGroup;
    
      constructor(private fb: FormBuilder){
    
      }
      // getter to get a reference to scheduleDetail form array in myForm form group
      get scheduleDetail():FormArray{
        return <FormArray>this.myForm.get('scheduleDetail')
      }
      // add a new row, get reference to form array using getter method and push form group into it   
      addRow(){
        this.scheduleDetail.push(this.initItems());
      }
      // make a form for each row!
      initItems(): FormGroup{
        return this.fb.group({
                  description: [null, Validators.required],
                  openTime: [null, Validators.required],
                  closeTime: [null, Validators.required]
              });
      }
    
      submit(){
        console.log(this.myForm.value)
      }
    
      ngOnInit() {
        this.myForm = this.fb.group({
          scheduleDetail: this.fb.array([this.initItems()])
        })
      }
    
    }
    

    模板

    <form [formGroup]="myForm" *ngIf="myForm">
        <table formArrayName="scheduleDetail">
            <thead> 
                <tr>
                  <th >Desc</th>
                  <th >Open Time</th>
                  <th >Close Time</th>
                </tr>
              </thead>
              <tbody>
                  <tr *ngFor="let item of myForm.controls.scheduleDetail.controls; let i=index"
                  [formGroupName]="i" >
                    <td><input type='text' formControlName="description"></td>
                    <td><input type='text' formControlName="openTime"></td>
                    <td><input type='text' formControlName="closeTime"></td>
                </tr>
              </tbody>
        </table>
    </form>
    
    <button (click)="addRow()">Add new item</button>
    <button (click)="submit()" [disabled]="!myForm.valid">Submit</button>
    

    【讨论】:

      猜你喜欢
      • 2017-11-22
      • 2017-11-02
      • 2017-09-14
      • 2017-09-12
      • 2017-02-11
      • 2017-04-29
      • 2017-08-22
      • 2017-12-30
      • 1970-01-01
      相关资源
      最近更新 更多