【问题标题】:Angular 2 requiring one of two items in a formgroupAngular 2 需要表单组中的两个项目之一
【发布时间】:2018-04-16 21:13:18
【问题描述】:

我正在尝试验证具有三个字段的反应式表单。用户名始终是必填字段,但我只希望用户除了输入用户名之外还必须输入电话号码或电子邮件,我不知道该怎么做。

我尝试过嵌套表单组和自定义验证器,我还尝试了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

【问题讨论】:

    标签: javascript forms angular validation


    【解决方案1】:

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

    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']) })
    });
    

    所以这里需要emailphoneNumber。如果你把它留空,那么任何带有值的控件都可以,你可以将它与任何类型的验证器一起使用,而不仅仅是Validators.required

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

    【讨论】:

    • 不错的解决方案!谢谢
    • 我使用了稍微不同的解决方案,但这很优雅!
    【解决方案2】:

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

    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

    【讨论】:

      猜你喜欢
      • 2022-11-11
      • 2017-04-22
      • 2016-05-07
      • 1970-01-01
      • 2022-10-15
      • 2015-10-28
      • 1970-01-01
      • 1970-01-01
      • 2017-08-28
      相关资源
      最近更新 更多