Angular 2需要表单组中的两个项目之一

时间:2017-11-04 05:04:49

标签: javascript forms angular validation

我正在尝试验证具有三个字段的被动表单。用户名始终是必填字段,但我只希望用户除了用户名之外还必须输入电话号码或电子邮件,我无法弄清楚如何操作。

我尝试过嵌套表单组和自定义验证程序,我也尝试了解决方案here,但没有运气。

这是我目前的html表单:

<div class="container"><br>
  <form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
    <div class="form-group">
      <label for="username">Username</label>
      <input type="text" id="username" formControlName="username" class="form-control">
      <span *ngIf="!signupForm.get('username').valid && hasBeenSubmitted == true" style="color: red">Please enter a valid username!</span>
    </div>
    <br><hr>
    <div formGroupName="userdata">
      <div class="form-group">
        <label for="email">email</label>
        <input type="text" id="email" formControlName="email" class="form-control">
      </div>
or <br>
      <div>
       <label for="phoneNumber">phone</label>
        <input type="text" formControlName="phoneNumber">
      </div>
    </div>
    <hr>
    <button class="btn btn-primary" type="submit">Submit</button>
        <span *ngIf="!signupForm.get('userdata.email').valid && hasBeenSubmitted == true && hasBeenSubmitted == true && !signupForm.get('userdata.email').valid 
        && hasBeenSubmitted == true" style="color: red">Please enter a valid email or phone number!</span>
  </form>
</div>

我的打字稿:

export class AppComponent implements OnInit {
  signupForm: FormGroup;
  hasBeenSubmitted = false;
  ngOnInit() {
    this.signupForm = new FormGroup({
      'username': new FormControl(null, Validators.required),
      'nickname': new FormControl(null, Validators.required),
      // Nested formgroup:
      'userdata': new FormGroup({
        'email': new FormControl(null, [Validators.required, Validators.email]),
        'phoneNumber': new FormControl(null, [Validators.required]),
      }),
    });
  }

  onSubmit() {
    this.hasBeenSubmitted = true; // I use this variable to validate after submission
  }
}

当用户提交没有电子邮件或电话号码的表单时,我希望错误文本为:Please enter a valid email or phone number!。当用户开始输入有效的电子邮件或电话号码时,这将解决。

如何验证我的表单,以便用户只需输入用户名和电话号码,或用户名和电子邮件,表单即可生效?

我当前代码的Plunkr: https://plnkr.co/edit/1IyVQblRX1bZxOXIpyQF?p=preview

2 个答案:

答案 0 :(得分:1)

正如您所说,您可以为组使用自定义验证器:

this.signupForm = new FormGroup({
  'username': new FormControl(null, Validators.required),
  'nickname': new FormControl(null, Validators.required),
   // Nested formgroup:
   'userdata': new FormGroup({
     'email': new FormControl(null),
     'phoneNumber': new FormControl(null),
    }, this.validateUserData)
});

其中validateUserData方法如下:

validateUserData(formGroup) {
  const emailCtrl = formGroup.get('email');
  const phoneCtr = formGroup.get('phoneNumber');

  if (emailCtrl.value && !Validators.email(emailCtrl) || phoneCtr.value) {
    return null;
  }

  return { required: true };
}

您需要做的最后一件事是更改模板,如:

<span *ngIf="!signupForm.get('userdata').valid && hasBeenSubmitted" ...>
  Please enter a valid email or phone number!
</span>

<强> Forked Plunker

答案 1 :(得分:1)

我创建了一个自定义验证程序指令:

Product
id | type    | name         
---+---------+---------------
 1 | game    | Goldeneye     
 2 | console | SNES          
 3 | cable   | HDMI          
 4 | game    | Smash Bros    
 5 | TV      | LG

Attributes
id | product_id | type        | value        
---+------------+-------------+---------
 1 | 1          | console     | N64
 2 | 4          | console     | Wii   
 3 | 5          | screen size | 50"

要使用它,只需执行以下操作:

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

  export const atLeastOne = (validator: ValidatorFn, controls:string[] = null) => (
    group: FormGroup,
  ): ValidationErrors | null => {
    if(!controls){
      controls = Object.keys(group.controls)
    }

    const hasAtLeastOne = group && group.controls && controls
      .some(k => !validator(group.controls[k]));

    return hasAtLeastOne ? null : {
      atLeastOne: true,
    };
  };

因此,此处需要this.signupForm = new FormGroup({ 'username': new FormControl(null, Validators.required), 'nickname': new FormControl(null, Validators.required), 'userdata': new FormGroup({ 'email': new FormControl(null), 'phoneNumber': new FormControl(null), }, { validator: atLeastOne(Validators.required, ['email','phoneNumber']) }) }); email。如果将其保留为空,则任何具有值的控件都可以,并且可以将其与任何类型的验证器一起使用,而不仅限于phoneNumber

这可以以任何形式重复使用。