npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ng-typesafe-formgroup

v0.0.5

Published

A ligthweight (just 19kb) Angular Reactive Form package that makes it's controls type safe and values asserted.

Downloads

5

Readme

Angular TypeSafe Reactive Forms

Reactive FormGroups Wrapped in a Type Safe Class

  • Improvements suggesions, bugs, errors, pull requests or become a contributor? Everything you need: https://github.com/pheetah/Angular-Type-Safe-Reactive-FormGroup
  • Check this examples on stackblitz: https://stackblitz.com/edit/ng-typesafe-formgroup?file=src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.ts

Installation and Basic Usage Guide

Implemented on Angular v13.2.x

Please click on dropdowns below for further information:

npm i ng-typesafe-formgroup
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...,
    FormsModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [...]
})
export class ...Module { }
import { FormControlTypeSafe, FormGroupTypeSafe } from 'ng-typesafe-formgroup';


interface CustomInterface{
  name: string,
  email: string,
  message: number,
};

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  typeSafeFormGroup = new FormGroupTypeSafe<CustomInterface>({
    name: new FormControlTypeSafe<CustomInterface["name"]>('', [Validators.required, Validators.minLength(5)]),
    email: new FormControlTypeSafe<CustomInterface["email"]>('', [Validators.required, Validators.maxLength(30)]),
    message: new FormControlTypeSafe<CustomInterface["message"]>('', [Validators.required, Validators.maxLength(100)])
  });

  \* you can now directly reach the controls! *\
  ngOnInit(){
    this.typeSafeFormGroup.controls.name
    this.typeSafeFormGroup.controls.message
    this.typeSafeFormGroup.controls.email
    this.typeSafeFormGroup.controls.email.value
    this.typeSafeFormGroup.controls.email.valueChanges.subscribe(a => console.log(a));
    this.typeSafeFormGroup.valueChanges.subscribe(a => console.log(a));
  }

}
import { FormControlTypeSafe, FormGroupTypeSafe } from 'ng-typesafe-formgroup';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  typeSafeFormGroupTypedWeak = new FormGroupTypeSafe({
    x: new FormControlTypeSafe('', [Validators.required])
  });

  ngOnInit(){
    this.typeSafeFormGroupTypedWeak.controls.x.value
    this.typeSafeFormGroupTypedWeak.controls.x.valueChanges.subscribe(a => console.log(a));
    this.typeSafeFormGroupTypedWeak.valueChanges.subscribe(a => console.log(a));
  }
}
    
  ...
  
  interface CustomInterface{
    name: string,
    email: string,
    message: number,
  };

  ...

  typeSafeFormGroup = new FormGroupTypeSafe<CustomInterface>({
    name: new FormControlTypeSafe<CustomInterface["name"]>('', [Validators.required, Validators.minLength(5)]),
    email: new FormControlTypeSafe<CustomInterface["email"]>('', [Validators.required, Validators.maxLength(30)]),
    message: new FormControlTypeSafe<CustomInterface["message"]>('', [Validators.required, Validators.maxLength(100)])
  });

  ...

and this way forms will asset your values on typeSafeFormGroup.valueChanges and typeSafeFormGroup.value such as ;

 typeSafeFormGroup.valueChanges.subscribe(val => val); \* val asserted as CustomInterface *\
 typeSafeFormGroup.value \* value asserted as CustomInterface \*

so that value is asserted correctly, unlike normal FormGroup class asserts everything as any!

  typeSafeFormGroupTypedWeak = new FormGroupTypeSafe({
    x: new FormControl('', [Validators.required])
  });

  constructor(){}

  ngOnInit(){
    this.typeSafeFormGroupTypedWeak.controls.x /* OK!
    this.typeSafeFormGroupTypedWeak.controls.a /* X->error! a is not a member of constructor object
  }

Important note

Be careful on value assertions. If you declare and interface and provide it to form group, values asserted on property types of interface. For example:

  interface CustomInterface{
    name: string,
    email: string,
    message: number,
  };

  typeSafeFormGroup = new FormGroupTypeSafe<CustomInterface>({
    name: new FormControlTypeSafe<CustomInterface["name"]>('', [Validators.required, Validators.minLength(5)]),
    email: new FormControlTypeSafe<CustomInterface["email"]>('', [Validators.required, Validators.maxLength(30)]),
    message: new FormControlTypeSafe<CustomInterface["message"]>('', [Validators.required, Validators.maxLength(100)])
  });

  this.typeSafeFormGroup.controls.email.value -> asserted as: string | number , because types on CustomInterfaces are string | number
  this.typeSafeFormGroup.controls.email.valueChanges.subscribe(a => console.log(a)); -> 'a' asserted as string | number
  this.typeSafeFormGroup.valueChanges.subscribe(a => console.log(a)); -> 'a' asserted as CustomInterface
  this.typeSafeFormGroup.value -> asserted as CustomInterface

If you don't provide an interface values asserted as "unknown". If you want to assign the value for example to a string (you expect it coming from the form), just basically do:

  typeSafeFormGroupTypedWeak = new FormGroupTypeSafe({
    x: new FormControlTypeSafe('', [Validators.required])
  });

  let x:string = <unknown> this.typeSafeFormGroupTypedWeak.controls.x.value as string;
  this.typeSafeFormGroupTypedWeak.controls.x.valueChanges.subscribe(a => a);



  this.typeSafeFormGroupTypedWeak.controls.x.value -> asserted as unknown

Please note that you can still use FormControl inside FormGroupTypeSafe instead of FormControlTypeSafe, but it's recommended to use FormControlTypeSafe.

Type safe forms prevents you from making mistakes

  • Transpiler warns you if you try to access an invalid control
  typeSafeFormGroupTypedWeak = new FormGroupTypeSafe({
    x: new FormGroupTypeSafe('', [Validators.required])
  });

  constructor(){}

  ngOnInit(){
    this.typeSafeFormGroupTypedWeak.controls.x /* OK!
    this.typeSafeFormGroupTypedWeak.controls.a /* X->error! a is not a member of constructor object
  }
  • If you provide an interface, you can not define a control that is not defined in the interface you provide
  interface FormControls{
    name: string,
    email: string,
    message: number,
  };

  typeSafeFormGroup = new FormGroupTypeSafe<FormControls>({
    name: new FormControlTypeSafe('', [Validators.required, Validators.minLength(5)]),
    email: new FormControlTypeSafe('', [Validators.required, Validators.maxLength(30)]),
    message: new FormControlTypeSafe('', [Validators.required, Validators.maxLength(100)]),
    outlier: new FormControlTypeSafe('', [Validators.required, Validators.maxLength(100)]) // X-> error! 'outlier' is not  FormControls property!
  })