Form state tracking helps you know if a user has changed or interacted with a form field and if the input is valid. This makes forms smarter and friendlier.
Form state tracking (dirty, touched, valid) in Angular
import { Component } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; @Component({ standalone: true, selector: 'app-simple-form', template: ` <input [formControl]="nameControl" aria-label="Name input" /> <div *ngIf="nameControl.touched && nameControl.invalid" role="alert"> Name is required. </div> <button [disabled]="!nameControl.dirty || nameControl.invalid">Submit</button> ` }) export class SimpleFormComponent { nameControl = new FormControl('', Validators.required); }
dirty means the user changed the value from the original.
touched means the user focused and then left the field.
valid means the current value passes all validation rules.
nameControl.dirty
nameControl.touched
nameControl.valid
nameControl.invalid
This component tracks the state of an email input. It shows messages only after the user touches the field and if the email is invalid. The submit button is enabled only if the user changed the input and the email is valid.
import { Component } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; @Component({ standalone: true, selector: 'app-form-state', template: ` <label for="email">Email:</label> <input id="email" type="email" [formControl]="emailControl" aria-describedby="emailHelp" [attr.aria-invalid]="emailControl.invalid" /> <div id="emailHelp" *ngIf="emailControl.touched && emailControl.invalid" role="alert" style="color: red;"> Please enter a valid email. </div> <p>Dirty: {{emailControl.dirty}}</p> <p>Touched: {{emailControl.touched}}</p> <p>Valid: {{emailControl.valid}}</p> <button [disabled]="!emailControl.dirty || emailControl.invalid">Submit</button> ` }) export class FormStateComponent { emailControl = new FormControl('', [Validators.required, Validators.email]); }
Use touched to avoid showing errors before the user interacts.
dirty helps to detect if the user made changes to the form.
Always combine these states to improve user experience in forms.
dirty means the user changed the input value.
touched means the user focused and left the input.
valid means the input passes validation rules.
Practice
dirty state indicate about a form control?Solution
Step 1: Understand the meaning of
Thedirtyin Angular formsdirtystate means the user has changed the value of the input from its original value.Step 2: Compare with other states
touchedmeans the user focused and left the input,validmeans the input passes validation, and disabled means the control is inactive.Final Answer:
The user has changed the input value. -> Option BQuick Check:
dirty = user changed input [OK]
- Confusing dirty with touched state
- Thinking dirty means input is valid
- Assuming dirty means input is disabled
email is touched in an Angular template?Solution
Step 1: Recall Angular form control access syntax
In Angular, form controls are accessed viaform.controls.controlNameorform.get('controlName'). Thetouchedproperty is a boolean, not a method.Step 2: Identify correct property usage
form.controls.email.touchedcorrectly accesses the touched property. Other options incorrectly use method calls or wrong property names.Final Answer:
form.controls.email.touched -> Option AQuick Check:
Access touched as property, not method [OK]
- Using parentheses like a method on touched
- Using incorrect property names like isTouched
- Accessing controls incorrectly with dot vs bracket
this.form = new FormGroup({
username: new FormControl('', Validators.required)
});
// User focuses on username input, types 'John', then leaves the input.What will be the values of
dirty, touched, and valid for username after these actions?Solution
Step 1: Analyze user actions on the form control
User focused and left the input, sotouchedis true. User changed the value from empty string to 'John', sodirtyis true.Step 2: Check validation status
The control hasValidators.required. Since 'John' is not empty, the control is valid, sovalidis true.Final Answer:
dirty: true, touched: true, valid: true -> Option DQuick Check:
Changed + left + valid input = dirty, touched, valid true [OK]
- Assuming dirty is false if user leaves input
- Confusing touched with dirty
- Thinking valid is false if user typed anything
<input type="text" formControlName="email">
<div *ngIf="form.controls.email.dirty && form.controls.email.valid">Valid email changed!</div>
But the message never shows even after typing a valid email. What is the likely problem?
Solution
Step 1: Understand the condition for showing the message
The message shows only if the control is bothdirtyandvalid.Step 2: Check if validation is set up
If the form control has an email validator but the input doesn't pass it (even if it looks valid),validis false, so the message won't appear.Final Answer:
The form control might have an email validator, so valid is false. -> Option CQuick Check:
Missing validator means valid stays false [OK]
- Thinking touched affects this condition
- Using wrong property names like isValid
- Assuming dirty never updates on input
<button [disabled]="???">Submit</button>
Solution
Step 1: Understand form state properties
pristinemeans no changes made, opposite ofdirty.invalidmeans form is not valid.Step 2: Translate requirement to condition
Disable button if form is pristine (no changes) or invalid (not valid). So disable whenform.pristine || form.invalid.Final Answer:
[disabled]="form.pristine || form.invalid" -> Option AQuick Check:
Disable if no changes or invalid [OK]
- Using dirty instead of pristine incorrectly
- Confusing valid with invalid
- Using touched instead of dirty/pristine
Ready to prove it?
Pass the test and this pattern moves unknown
