You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 5自定义密码匹配验证器遇TypeError:无法读取undefined的'password'属性

解决Angular Material密码匹配验证的TypeError问题(避免ReactiveForms/FormGroup)

嘿,我明白你不想用Reactive Forms的FormGroup来做这个验证的需求,咱们直接用模板驱动表单+自定义验证器类来搞定这个问题,顺便解决那个TypeError!

首先,先说说你遇到的TypeError大概率是因为:

  • 验证器里没有正确获取到两个密码控件的引用
  • 验证器的返回格式不符合Angular的要求
  • 模板里没有正确把验证器绑定到合适的控件组上

步骤1:创建密码匹配验证器类

咱们写一个实现Validator接口的验证器,专门用来检查两个密码字段是否匹配:

import { Validator, AbstractControl, ValidationErrors } from '@angular/forms';
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class PasswordMatchValidator implements Validator {
  validate(control: AbstractControl): ValidationErrors | null {
    // 获取密码和确认密码控件
    const password = control.get('password');
    const confirmPassword = control.get('confirmPassword');

    // 先检查控件是否存在,避免TypeError
    if (!password || !confirmPassword) {
      return null;
    }

    // 如果两个字段值不匹配,返回错误对象
    if (password.value !== confirmPassword.value) {
      return { passwordMismatch: true };
    }

    // 匹配成功返回null
    return null;
  }
}

这里关键是先判断控件是否存在,这能避免你遇到的TypeError——如果控件没正确找到,直接返回null就不会报错了。

步骤2:组件类准备

在你的组件里注入这个验证器,同时定义表单相关的属性(模板驱动表单用ngModel绑定):

import { Component, OnInit } from '@angular/core';
import { PasswordMatchValidator } from './password-match.validator';

@Component({
  selector: 'app-password-form',
  templateUrl: './password-form.component.html',
  styleUrls: ['./password-form.component.css']
})
export class PasswordFormComponent implements OnInit {
  password: string = '';
  confirmPassword: string = '';

  constructor(public passwordMatchValidator: PasswordMatchValidator) { }

  ngOnInit(): void { }
}

步骤3:Angular Material模板实现

用ngModelGroup把两个密码字段包裹起来,然后把咱们的验证器绑定到这个group上,这样就能实现跨字段验证,还不用全局的FormGroup:

<form #passwordForm="ngForm">
  <div ngModelGroup="passwordGroup" [validator]="passwordMatchValidator">
    <!-- 密码输入框 -->
    <mat-form-field appearance="fill">
      <mat-label>密码</mat-label>
      <input 
        matInput 
        type="password" 
        name="password" 
        [(ngModel)]="password" 
        required
        #passwordCtrl="ngModel">
      <mat-error *ngIf="passwordCtrl.invalid">
        请输入密码
      </mat-error>
    </mat-form-field>

    <!-- 确认密码输入框 -->
    <mat-form-field appearance="fill">
      <mat-label>确认密码</mat-label>
      <input 
        matInput 
        type="password" 
        name="confirmPassword" 
        [(ngModel)]="confirmPassword" 
        required
        #confirmPasswordCtrl="ngModel">
      <mat-error *ngIf="confirmPasswordCtrl.invalid">
        请确认密码
      </mat-error>
      <mat-error *ngIf="passwordForm.get('passwordGroup')?.hasError('passwordMismatch')">
        两次输入的密码不匹配
      </mat-error>
    </mat-form-field>
  </div>

  <!-- 提交按钮 -->
  <button mat-raised-button color="primary" [disabled]="passwordForm.invalid">
    提交
  </button>
</form>

关键说明

  • 用ngModelGroup来包裹需要验证的两个字段,这样验证器就能拿到这两个控件的引用,避免TypeError
  • 验证器里先判断控件是否存在,防止因为控件未初始化导致的TypeError
  • Angular Material的mat-error可以通过表单或控件的hasError方法来显示对应的错误信息

这样设置后,当两次密码输入不一致时,就会显示“两次输入的密码不匹配”的错误,而且不会出现TypeError啦!

内容的提问来源于stack exchange,提问作者tmott13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:00:14