Lesson 7 — Strictly typed reactive forms¶
Objective¶
Model a study-session workflow with strict values, accessible validation, explicit disabled-state semantics, and safe submission behavior.
Prerequisites¶
TypeScript nullability, component events, domain commands, and route navigation.
Mental model¶
A reactive form explicitly models values, validity, interaction, and disabled state. Native validation helps users; Angular validators protect the client model; the server remains authoritative.
Why it exists¶
Forms coordinate user input, business rules, accessibility, async work, and transport commands. Strong types expose mismatches before runtime.
Working model: valid controls produce a typed value.
Engineering reality: disabled controls are excluded from
value;getRawValue()includes them. Neither choice proves that every field belongs in the server command.
Minimal example¶
new FormControl(30, {
nonNullable: true,
validators: [Validators.required, Validators.min(5), Validators.max(240)]
});
Real-world usage¶
Create/edit workflows need cross-field rules, server validation, pending states, duplicate-submit prevention, error focus, and intentional reset behavior.
Common mistakes¶
- using placeholders as labels;
- showing errors before meaningful interaction;
- casting form values to silence model mismatch;
- confusing disabled presentation with command membership;
- allowing duplicate async submissions.
Mini lab¶
Task: Build non-nullable topic/minutes/notes controls with required/range/length and cross-field validation. Mark invalid submission, focus or summarize errors, submit a typed command, and reset explicitly.
Constraints: associate errors with controls, announce success, prevent duplicate submission, and use no casts to satisfy the store input.
Expected result: untouched, invalid, valid, pending, success, and reset states behave predictably for keyboard and assistive-technology users.
Hint 1
Define the domain command independently, then make the form's raw value satisfy it intentionally.
Hint 2
Advanced topics require either sufficient minutes or detailed notes; that rule belongs at group level.
Solution direction — last resort
Use non-nullable controls, group validation, markAllAsTouched, explicit defaults on reset, and getRawValue() only when disabled fields belong in the command.
Verification¶
Test through the DOM. Disable one control, compare value and getRawValue(), and decide whether inclusion is correct rather than automatically switching APIs.
Mastery evidence: submit a strictly typed command, implement accessible error behavior, and diagnose a missing disabled value.
Bloom challenge¶
- Understand: value, validity, touched, dirty, pending, disabled.
- Apply: add typed cross-field validation.
- Analyze: debug an incomplete payload.
- Evaluate: client, cross-field, async, or server validation placement.
- Create: design a resilient edit form with conflict and retry behavior.
Summary¶
A form is a stateful workflow boundary; strict types and accessible feedback make its assumptions visible, while the server enforces trust.
Spaced review¶
Retrieve parent/child ownership from Lesson 3. Lesson 10 verifies form behavior through public DOM interactions.
What comes next¶
Continue to HTTP and asynchronous state. Optionally compare experimental Signal Forms only after mastering the stable baseline.