如何分别校验用户名与密码?Angular表单错误提示异常求助
Hey there! Let’s tackle your two problems one by one—first that annoying double error message glitch, then how to validate your username and password separately.
1. Fixing the Dual Error Message Problem
Your hunch about #name and ngModel is spot-on! The most likely culprit is that your error messages are tied to the entire form’s state instead of individual input controls, or you’re reusing the same template reference variable for both inputs.
Example of What Might Be Wrong
If your template looks like this, touching either input will trigger both messages because they’re listening to the whole form’s touched state:
<!-- ❌ Bad: Errors tied to the entire form --> <form #loginForm="ngForm"> <input type="text" name="username" [(ngModel)]="user.username" required> <input type="password" name="password" [(ngModel)]="user.password" required> <div *ngIf="loginForm.invalid && loginForm.touched"> <p>enter username</p> <p>enter password</p> </div> </form>
Or maybe you’re using the same template variable for both inputs:
<!-- ❌ Bad: Reusing the same ngModel reference --> <input type="text" name="username" [(ngModel)]="user.username" #inputCtrl="ngModel" required> <input type="password" name="password" [(ngModel)]="user.password" #inputCtrl="ngModel" required> <div *ngIf="inputCtrl.invalid && inputCtrl.touched"> <p>enter username</p> <p>enter password</p> </div>
The Fix
Bind each error message to its own input’s state using unique template references:
<!-- ✅ Good: Individual control tracking --> <form #loginForm="ngForm"> <!-- Username input with unique reference --> <input type="text" name="username" [(ngModel)]="user.username" #usernameCtrl="ngModel" required> <!-- Username error --> <div *ngIf="usernameCtrl.invalid && usernameCtrl.touched"> <p>enter username</p> </div> <!-- Password input with unique reference --> <input type="password" name="password" [(ngModel)]="user.password" #passwordCtrl="ngModel" required> <!-- Password error --> <div *ngIf="passwordCtrl.invalid && passwordCtrl.touched"> <p>enter password</p> </div> </form>
If you’re using reactive forms, make sure you check the specific control instead of the whole form:
<!-- For reactive forms --> <div *ngIf="loginForm.get('username').invalid && loginForm.get('username').touched"> <p>enter username</p> </div>
2. Separating Username & Password Validation
You can add custom or built-in validators to each input independently—here’s how to do it for both template-driven and reactive forms.
Option 1: Reactive Forms (Recommended for Complex Validation)
In your login.ts, build a form group with separate validators for each field:
import { FormBuilder, Validators } from '@angular/forms'; @Component({ selector: 'app-login', templateUrl: './login.html' }) export class LoginComponent { // Build form with separate validation rules loginForm = this.fb.group({ username: ['', [ Validators.required, Validators.minLength(3), // At least 3 chars Validators.pattern('^[a-zA-Z0-9_]+$') // Only letters, numbers, underscores ]], password: ['', [ Validators.required, Validators.minLength(6), // At least 6 chars Validators.pattern('^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{6,}$') // Letters + numbers ]] }); constructor(private fb: FormBuilder) {} // Getters for easy template access get username() { return this.loginForm.get('username'); } get password() { return this.loginForm.get('password'); } onSubmit() { if (this.loginForm.valid) { // Handle login logic } } }
Then in your login.html, show specific errors for each field:
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()"> <div> <label>Username</label> <input formControlName="username" type="text"> <div *ngIf="username.invalid && username.touched"> <p *ngIf="username.errors.required">enter username</p> <p *ngIf="username.errors.minlength">Username must be at least 3 characters</p> <p *ngIf="username.errors.pattern">Username can only contain letters, numbers, and underscores</p> </div> </div> <div> <label>Password</label> <input formControlName="password" type="password"> <div *ngIf="password.invalid && password.touched"> <p *ngIf="password.errors.required">enter password</p> <p *ngIf="password.errors.minlength">Password must be at least 6 characters</p> <p *ngIf="password.errors.pattern">Password needs at least one letter and one number</p> </div> </div> <button type="submit" [disabled]="loginForm.invalid">Login</button> </form>
Option 2: Template-Driven Forms
For simpler cases, you can add validators directly in the template and create custom validation functions in login.ts:
import { NgForm } from '@angular/forms'; @Component({ selector: 'app-login', templateUrl: './login.html' }) export class LoginComponent { user = { username: '', password: '' }; // Custom username validator validateUsername(control: any) { const isValid = /^[a-zA-Z0-9_]+$/.test(control.value); return isValid ? null : { invalidUsername: true }; } // Custom password validator validatePassword(control: any) { const isValid = /^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{6,}$/.test(control.value); return isValid ? null : { invalidPassword: true }; } onSubmit(form: NgForm) { if (form.valid) { // Handle login } } }
Template:
<form #loginForm="ngForm" (ngSubmit)="onSubmit(loginForm)"> <div> <label>Username</label> <input type="text" name="username" [(ngModel)]="user.username" #usernameCtrl="ngModel" required minlength="3" [ngModelValidator]="validateUsername" > <div *ngIf="usernameCtrl.invalid && usernameCtrl.touched"> <p *ngIf="usernameCtrl.errors.required">enter username</p> <p *ngIf="usernameCtrl.errors.minlength">Username must be at least 3 characters</p> <p *ngIf="usernameCtrl.errors.invalidUsername">Invalid username format</p> </div> </div> <div> <label>Password</label> <input type="password" name="password" [(ngModel)]="user.password" #passwordCtrl="ngModel" required minlength="6" [ngModelValidator]="validatePassword" > <div *ngIf="passwordCtrl.invalid && passwordCtrl.touched"> <p *ngIf="passwordCtrl.errors.required">enter password</p> <p *ngIf="passwordCtrl.errors.minlength">Password must be at least 6 characters</p> <p *ngIf="passwordCtrl.errors.invalidPassword">Password needs letters + numbers</p> </div> </div> <button type="submit" [disabled]="loginForm.invalid">Login</button> </form>
Quick Recap
- Double error fix: Make sure each error message is tied to its own input’s
touched/invalidstate, not the whole form or a shared reference. - Separate validation: Add unique validators (built-in or custom) to each input control, either via reactive form groups or template-driven directives.
内容的提问来源于stack exchange,提问作者omkar

