This talk may contain strong language, harsh truths, and serious passion.
“Why’d you have to go and make things so complicated?”
- Avril Lavigne, implementing Angular forms in 2019
Template-driven Forms vs. Reactive Forms
When events occur, code runs and
changes the state of the program.
Specifying HOW values should be generated.
Reactive - A declarative programming style concerned with data “streams” and
propagation of change. RxJS is a reactive
programming JavaScript library.
The basic element of building Angular forms is the FormControl. This is a class that represents that input element on a page with a name value you’re likely used to seeing.
FormGroup is the class that allows us to group a number of controls together. It also extends the AbstractControl class, meaning we can track the validity and value of all the FormControls in a FormGroup together.
This allows us to easily manage our form as a whole. The `[formGroup]` directive binds the FormGroup to a DOM element.
FormArray is a class that aggregates FormControls into an array, similar to FormGroup creating an object from FormControls.
FormArrays can have controls pushed to them or removed from them similar to the way you’d manipulate an array in vanilla JS, and offer us a lot of power and flexibility when creating nested and dynamic forms.
Repeatedly typing new FormControl(''), new FormGroup({}), and new FormArray([]) can become a bit tedious, especially when creating larger forms.
Angular has shorthand syntax we can use thanks to the FormBuilder class.
I need dynamic required fields
We can do this pretty easily by marking them as touched.
I need custom validation rules
I need to display one thing in an input field
for the user but submit something else
Likely use case: the library I’m
using doesn’t play nice with reactive forms.
Not as scary as it sounds - it's just a way to build a custom input.
From the docs: Defines an INTERFACE that acts as a bridge between the Angular forms API and a native element in the DOM.
Writes new value to the element.
Registers a callback function that is called when
the control's value changes in the UI.
Registers a callback function is called by the forms
API on initialization to update the form model on blur.
Returns a boolean value when a
formControl's disabled status changes
CVA is great for granular control of displaying
to the UI and communicating with the forms API
You can use the CVA to create reusable form
elements instead of drowning in event emitter soup!
I need to dynamically add and
remove form controls & form groups
I want parts of a form nested across components or routes
The ControlContainer is a base class for form directives that contain multiple registered instances of NgControl. We can use the ControlContainer to access FormControls, FormGroups, and FormArrays and manage a main form chunked across components.
You can get into some sketchy situations
listening for formControl changes and acting on them.
patchValue(value: any, opts: {
onlySelf?: boolean;
emitEvent?: boolean;
} = {}): void
Take advantage of the options param
and don't emit an event on your changes.
When initializing a formControl to use with a component implementing the CVA interface the disabled status must be set(whether enabled or disabled) to ensure the formControl behaves properly.
Demo code: https://github.com/tehfedaykin/ControlContainerExample
Avril's New Single: Head Above Water
Slides available at: tehfedaykin.github.io/complicatedNGforms
Need help with Angular? Work with me! jennifer@bitovi.com