Skip to content

Because FormControl<T> is more awesome than FormControl!

License

Notifications You must be signed in to change notification settings

armandcolenati/ngx-typesafe-forms

 
 

Repository files navigation

Type-safe Forms for Angular 📝

Because FormControl<T> is more awesome than FormControl!

NPM version NPM downloads Build status All Contributors

Overview

What? 🤔

This is a small library to make Angular Forms more type-safe!

  • Type-safe versions of FormControl, FormGroup, FormArray and ControlValueAccessor
  • 100% compatible with @angular/forms and existing Angular libraries!
  • Easy to use!
  • Additional read-only properties value$, valid$, pristine$, errors$, enabled$ and more.
  • A default implementation for ControlValueAccessor
  • Type-safe validators

Why? 🤷‍♂️

Angular Forms are not very type-safe. They accept any type of value. This library makes your code more type-safe. More type-safety means smaller risk for bugs!

Installation 🌩

npm
npm install ngx-typesafe-forms
yarn
yarn add ngx-typesafe-forms

Usage 🕹

Basic example

Just import your FormControl, FormGroup, FormArray and ControlValueAccessor from ngx-typesafe-forms instead of @angular/forms and you are done!

import { FormControl, FormGroup } from 'ngx-typesafe-forms';

@Component({ /* ... */ })
class YourComponent {
  myControl = new FormControl<string>();
  
  myFormGroup = new FormGroup<Person>({
    name: new FormControl(),
    birthDate: new FormControl(new Date())
  });
  
  changeDate(): void {
    this.myControl.setValue(123); // error: this will not compile!
    this.myFormGroup.controls.birthDate.setValue('foo'); // error: this will not compile!
    
    this.myControl.setValue('Foo'); // yes, this will!
    this.myFormGroup.controls.birthDate.setValue(new Date()); // yes, this will!
  }
}

Additional reactive properties

Besides the type-safety, we also provide additional reactive properties.

const myControl = new FormControl<string>('bar');

// subscribe to all values, including the existing value!
myControl.value$.subscribe((value) => {
  /* ... */
});

// subscribe to validity changes, including the existing valid state!
myControl.valid$.subscribe((valid) => {
  /* ... */
});

The recommended properties are:

  • value$
  • errors$
  • enabled$
  • pristine$
  • valid$
  • status$
  • validValue$

Additionally, we also provide some of their counterparts:

  • disabled$
  • dirty$
  • invalid$

NOTE: all of these streams also include the current (initial) values.

FAQ

How to deal with validation and null values?

If you want to assume that form values are always valid, just use FormControl<Foo>.

However, form values can also be null (if invalid). If you want to use this more strictly, you can use FormControl<Foo | null> or even FormGroup<Invalidated<Foo>> (which marks all properties as nullable).

Help, my myFormGroup.controls.foo is an optional AbstractControl!

Sometimes, it's not guaranteed that a FormGroup contains a certain form control, or that it is actually a FormControl (it could also be a FormArray).

For that reason, we introduced new methods to FormGroup in version 1.3.0:

  • FormGroup.getControl(name: string) - returns a AbstractControl, throws error if it was not found.
  • FormGroup.getFormControl(name: string) - returns a FormControl, throws error if it was not found or not instance of FormControl.

The same applies for FormArray.at(index: number), which returns a AbstractControl. For that reason we introduced:

  • FormArray.controlAt(index: number) - returns a FormControl, throws error if it is not an instance of FormControl.

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Dirk Luijk

💻 📖

Daan Scheerens

🤔

Jur Balledux

🐛 💻

This project follows the all-contributors specification. Contributions of any kind welcome!

About

Because FormControl<T> is more awesome than FormControl!

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 96.4%
  • HTML 3.1%
  • Other 0.5%