如何手动将我的 mdbootstrap angular.js 表单中的输入标记为无效?

How can I manually mark an input in my mdbootstrap angular.js form as invalid?

使用我当前的代码,如果输入为空或不符合输入类型的格式(例如:电子邮件必须具有“@”和“.”格式),我可以使输入显示为无效。

我的下一步是确保密码和确认密码字段匹配。我已经创建了一个比较两者的函数,但是在使用 mdbootstrap 表单实现它时遇到了很多麻烦。

我一直在玩的功能:

mustMatch(controlName: string, matchingControlName: string) {
return (formGroup: FormGroup) => {
  const control = formGroup.controls[controlName];
  const matchingControl = formGroup.controls[matchingControlName];

  if (matchingControl.errors && !matchingControl.errors.mustMatch) {
    // var passwordInput = document.getElementById('password');
    // passwordInput.classList.remove('ng-valid');
    // passwordInput.classList.add('ng-invalid');
    formGroup.controls['password'].setErrors({'incorrect': true});
    return;
  }

  if (control.value !== matchingControl.value) {
    matchingControl.setErrors({ mustMatch: true });
  } else {
    matchingControl.setErrors(null);
  }
};

}

我需要使无效的元素:

<div class="col-xs-12">
      <div class="form-outline">
        <input formControlName="password" type="password" id="password" class="form-control pb-3" required/>
        <label class="form-label" for="password">Password</label>
        <div class="invalid-feedback">Please enter your password.</div>
      </div>
    </div>

    <div class="col-xs-12">
      <div class="form-outline">
        <input formControlName="confirmPassword" type="password" id="confirmPass" class="form-control pb-3" required/>
        <label class="form-label" for="confirmPass">Confirm Password</label>
        <div class="invalid-feedback">Please confirm your password.</div>
      </div>
    </div>

窗体的初始化:

ngOnInit(): void {
document.querySelectorAll('.form-outline').forEach((formOutline) => {
  new mdb.Input(formOutline).init();
});
this.setupSignupForm();

const forms = document.querySelectorAll('.needs-validation');

Array.prototype.slice.call(forms).forEach((form) => {
  form.addEventListener('submit', (event) => {
    if (!form.checkValidity()) {
      event.preventDefault();
      event.stopPropagation();
    }
    form.classList.add('was-validated');
  }, false);
});



setupSignupForm(): void {
    this.signupForm = this.formBuilder.group({
      firstName: ['', Validators.required],
      lastName: ['', Validators.required],
      email: ['',
        [
          Validators.required,
          Validators.email,
        ]],
      confirmEmail: ['',
        [
          Validators.required,
          Validators.email,
        ]],
      joinCode: ['', Validators.required],
      password: ['', Validators.required],
      confirmPassword: ['',
        [
          Validators.required,
        ]]
    }, {
      validators: [this.mustMatch('password', 'confirmPassword'), this.mustMatch('email', 'confirmEmail')]
    });
  }

如果您能弄清楚如何做到这一点,请告诉我。在这个问题上我一直在用头撞墙!

Here is a picture of what I am dealing with:

我认为最好为每个 form-control 使用 validator 而不是整个 form-group,因为:

  • form-group 验证器将检查表单中的任何更改,即使这些更改与目标 form-control(s)(passwordemail 在你的情况下)。
  • 您必须手动设置错误 (setErrors),并以相同的方式删除它们。

相反,您可以通过将验证器分配给 form-control 本身来实现它,如下所示:

setupSignupForm(): void {
  this.signupForm = this.formBuilder.group({
    firstName: ['', Validators.required],
    lastName: ['', Validators.required],
    email: ['', [Validators.required, Validators.email]],
    confirmEmail: [
      '',
      [Validators.required, Validators.email, this.mustMatch('email')]
    ],
    joinCode: ['', Validators.required],
    password: ['', Validators.required],
    confirmPassword: ['', [Validators.required, this.mustMatch('password')]]
  });
}

mustMatch(matchingControlName: string): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    if (!control.parent) return;

    const matchingCtrlValue = control.parent.get(matchingControlName).value;

    if (control.value !== matchingCtrlValue) {
      return { mustMatch: true };
    } else {
      return null;
    }
  };
}

mdboostrat 验证可以将 :invalid 和 :valid 样式添加到父 .was-validated class。但是您也可以在您的输入中添加 class is-valid 或 is-invalid (而不是在表单中添加 was-validated)

所以我建议另一种方法:

1.-在您的代码中删除

/**Remove this lines**
const forms = document.querySelectorAll('.needs-validation');

Array.prototype.slice.call(forms).forEach((form) => {
  form.addEventListener('submit', (event) => {
    ...
});

2.-在你的输入中使用

<input [ngClass]="'is-valid':form.get('password').invalid && 
                   form.get('password').touched;
                  'is-invalid':form.get('password').valid && 
                   form.get('password').touched">

好吧,在我们所有的输入中重复一遍,ngClass 有点“奇怪”。那么,为什么不使用为我们制定的指令呢?

想象一下这样的指令

@Directive({
  selector: '.form-control'
})
export class MdClassDirective {
  @HostBinding('class.is-valid') get valid() {
    return (
      (!this.form || this.form.classList.contains('submitted')) &&
      this.control &&
      this.control.touched &&
      this.control.valid
    );
  }
  @HostBinding('class.is-invalid') get invalid() {
    return (
      (!this.form || this.form.classList.contains('submitted')) &&
      this.control &&
      this.control.touched &&
      this.control.invalid
    );
  }
  form: any;
  constructor(@Optional() private control: NgControl, el: ElementRef) {

    //we need get the "html form"
    this.form = el.nativeElement;

    while (this.form.parentElement && !(this.form instanceof HTMLFormElement)) {
      this.form = this.form.parentElement;
    }
  }
}

此指令将 class 有效或无效添加到您的输入中 class “form-control” if is touched and the “form” has as class提交。所以这项工作以 html 形式,例如-查看 [[=​​33=]]="已提交"-

<form [formGroup]="form" (submit)="submitted=true;submit()" 
      [class.submitted]="submitted">
  <input class="form-control" formControlName="name" >
  <button>submit</button>
</form>

不要忘记在提交的函数中将元素标记为输入

  submit() {
    this.form.markAllAsTouched();
  }

这样就可以在Angular中正常使用customValidator了。