使用模板驱动表单和Angular 2中的NgFor进行单选按钮验证

时间:2017-01-17 02:36:12

标签: angular angular2-forms

有人可以解释一下为什么在尝试验证单选按钮而不使用NgFor时这些选项有效:

@Component({
  selector: 'rio-app',
  template: `
    <form #myForm="ngForm">

      <label>
        Male: 
        <input type="radio" name="gender" value="Male" 
          ngModel required #gender="ngModel"
        />
      </label>

      <label>
        Female: 
        <input type="radio" name="gender" value="Female" 
          ngModel required #gender="ngModel"
        />
      </label>

      <div [hidden]="!gender.hasError('required')">
        The gender is required
      </div>

    </form>
  `
})
export class AppComponent {}

Plunker

但如果我尝试使用NgFor做同样的事情,那就失败了:

@Component({
  selector: 'rio-app',
  template: `
    <form #myForm="ngForm">

      <label *ngFor="let gender of genders">
        {{ gender }}: 
        <input type="radio" name="gender" [value]="gender" 
          ngModel required #myGender="ngModel"
        />
      </label>

      <div [hidden]="!myGender.hasError('required')">
        The gender is required
      </div>

    </form>
  `
})
export class AppComponent {
  genders = ['Male', 'Female']
}

Plunker

我在浏览器的控制台中收到一条错误消息:

Cannot read property 'hasError' of undefined

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

所以我最终在Angular回购中开了一个issue,一个人(@alexzuza)给了我一个很好的答案,我想与你分享以供将来参考:

re.split()

据我了解,诀窍是使用import { Component } from '@angular/core'; @Component({ selector: 'rio-app', template: ` <form #myForm="ngForm"> <input type="text" /> <ng-container *ngFor="let gender of genders; let isLast = last"> <label> {{ gender }}: <input type="radio" name="gender" [value]="gender" ngModel required #myGender="ngModel" /> </label> <div *ngIf="isLast" [hidden]="!myGender.hasError('required')"> The gender is required </div> </ng-container> </form> ` }) export class AppComponent { genders = ['Male', 'Female'] } NgFor内部完成所有操作,因为在循环内创建的每个变量都有块范围。

这是一个有效的plunker

答案 1 :(得分:2)

查看第二个plunker似乎在#myGender中定义的模板引用变量*ngFor在外部不可见,即在该错误消息中div

但是你确实可以在该级别访问#myForm,因此您可以使用它来检查性别FormControl上的错误。

<div [hidden]="!myForm.controls.gender?.hasError('required')">
    The gender is required
</div>

从Angular doco我知道*ngFor定义中定义的性别变量不可见但我不确定该块内的模板变量。其他人可能会为我们提供更好的解释。

答案 2 :(得分:1)

我不知道为什么'myGender'未定义,我不知道如何使用普通的FormsModule来解决这个问题,对你完全诚实,我知道如何使用'ReactiveFormsModule'解决这个问题。

在AppModule中,您必须从

更改Forms模块导入
import { FormsModule } from '@angular/forms';

import { ReactiveFormsModule } from '@angular/forms';

并更改@NgModule中的导入

@NgModule({
  imports: [ BrowserModule, FormsModule ],
  declarations: [ AppComponent ],
  bootstrap: [ AppComponent ]
})

您现在必须在组件中导入一些新东西

import { FormGroup, FormBuilder, Validators } from '@angular/forms';

你必须为ReactiveFormsModule稍微更改一下你的表单     

  <label *ngFor="let gender of genders">
    {{ gender }}: 
    <input type="radio" name="gender" [value]="gender" 
       required [formControl]="myForm.controls['gender']"
    />
  </label>

  <div [hidden]="!myForm.controls['gender'].hasError('required')">
    The gender is required
  </div>

</form>

现在您可以使用表单构建器来定义表单控件和验证器

export class AppComponent {
  genders = ['Male', 'Female'];
  myForm : FormGroup;

  constructor(private formBuilder: FormBuilder){
    this.myForm = this.formBuilder.group({
      'gender' : [null, Validators.required]
    });
  }
}

如果您真的想使用for循环,这是我现在解决此问题的唯一方法。

编辑:

Plnkr example