Angular Web Framework Reactive Forms & Validation 5 — Questions and Answers
Question 1: What is the correct way to provide a custom async validator as a class implementing `AsyncValidator`?
- Implement the `validate()` method returning Observable<ValidationErrors | null> or Promise<ValidationErrors | null> (Correct answer)
- Implement `asyncValidate()` returning a boolean observable
- Extend `AbstractControl` and override `runAsync()`
- Decorate the class with @AsyncValidator()
Correct answer: Implement the `validate()` method returning Observable<ValidationErrors | null> or Promise<ValidationErrors | null>
Classes implementing `AsyncValidator` must define `validate()` returning an observable or promise that resolves to an error map or null.
Question 2: Which FormArray property tells you how many controls it currently contains?
- length (Correct answer)
- count
- size
- controls.total
Correct answer: length
`FormArray.length` returns the number of controls currently in the array, mirroring the standard array API.
Question 3: When using `nonNullable: true` in a FormControl, what happens when `reset()` is called?
- The control resets to its initial value instead of null (Correct answer)
- The control cannot be reset at all
- The control resets to an empty string
- An error is thrown
Correct answer: The control resets to its initial value instead of null
A non-nullable FormControl stores its initial value and restores it on `reset()` rather than defaulting to null.
Question 4: What does `Validators.composeAsync()` do?
- Merges multiple async validators into one that runs them in parallel and combines their errors (Correct answer)
- Runs async validators sequentially, stopping at the first error
- Converts synchronous validators to async ones
- Creates a lazy validator that only runs on submit
Correct answer: Merges multiple async validators into one that runs them in parallel and combines their errors
`Validators.composeAsync()` combines an array of async validators, runs them concurrently, and merges all returned errors.
Question 5: Which technique prevents an async validator from firing on every keystroke by caching the last checked value?
- Return the cached result immediately if the value hasn't changed since the last check (Correct answer)
- Use updateOn: 'submit' on the control
- Call control.clearAsyncValidators() after the first run
- Wrap the validator in debounceTime() inside the validate() method
Correct answer: Return the cached result immediately if the value hasn't changed since the last check
Storing the previously validated value and returning the cached error map when the value is unchanged avoids redundant HTTP calls.
Question 6: How do you reactively display an error message only after the user has interacted with a field?
- Check control.invalid && control.touched in the template (Correct answer)
- Check control.invalid && control.dirty in the template
- Check control.errors !== null only
- Subscribe to statusChanges and set a local error flag
Correct answer: Check control.invalid && control.touched in the template
Combining `invalid` with `touched` ensures the error appears only after the user has visited the field, not on initial load.
Question 7: What is the effect of calling `control.clearValidators()` followed by `control.updateValueAndValidity()`?
- Removes all sync validators and immediately re-evaluates the control, making it valid (Correct answer)
- Removes validators but keeps the existing error map until the next user interaction
- Throws an error if the control currently has errors
- Only affects async validators
Correct answer: Removes all sync validators and immediately re-evaluates the control, making it valid
`clearValidators()` detaches all sync validators, and `updateValueAndValidity()` forces re-evaluation so the control becomes valid (assuming no async errors).
What is the correct way to provide a custom async validator as a class implementing `AsyncValidator`?