Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Sweet Angular, good forms never felt so good

Ciro Nunes
November 17, 2017

Sweet Angular, good forms never felt so good

Ciro Nunes

November 17, 2017
Tweet

More Decks by Ciro Nunes

Other Decks in Programming

Transcript

  1. import { NgModule } from '@angular/core'; import { BrowserModule }

    from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; @NgModule({ imports: [ BrowserModule, FormsModule ] }) export class AppModule {}
  2. abstractControl properties valid dirty invalid touched pending status disabled untouched

    enabled *statusChanges errors *valueChanges pristine path
  3. abstractControl properties valid dirty invalid touched pending status disabled untouched

    enabled *statusChanges errors *valueChanges pristine path *: Observable
  4. import { NgModule } from '@angular/core'; import { BrowserModule }

    from '@angular/platform-browser'; import { ReactiveFormsModule } from '@angular/forms'; @NgModule({ imports: [ BrowserModule, ReactiveFormsModule ] }) export class AppModule {}
  5. constructor(private fb: FormBuilder) { this.heroForm = fb.group({ name: ['', [Validators.required,

    Validators.minLength(3)]], rival: [], superpowers: fb.group({ invisibility: false, fly: false, nightVision: false, healing: false }, { validator: superpowersValidator }), sex: [], skills: fb.group({ programming: 0, bjj: 0, fifa: 0 }), github: [] }); }
  6. constructor(private fb: FormBuilder) { this.heroForm = fb.group({ name: ['', [Validators.required,

    Validators.minLength(3)]], rival: [], superpowers: fb.group({ invisibility: false, fly: false, nightVision: false, healing: false }, { validator: superpowersValidator }), sex: [], skills: fb.group({ programming: 0, bjj: 0, fifa: 0 }), github: [] }); }
  7. constructor(private fb: FormBuilder) { this.heroForm = fb.group({ name: ['', [Validators.required,

    Validators.minLength(3)]], rival: [], superpowers: fb.group({ invisibility: false, fly: false, nightVision: false, healing: false }, { validator: superpowersValidator }), sex: [], skills: fb.group({ programming: 0, bjj: 0, fifa: 0 }), github: [] }); }
  8. export const superpowersValidator = (control: AbstractControl) "' { const invisibility

    = control.get('invisibility'); const fly = control.get('fly'); const healing = control.get('healing'); const nightVision = control.get('nightVision'); const fields = [invisibility, fly, healing, nightVision] .filter(field "' field.value ""( true); if (fields.length < 2) { return { atleasttwo: true }; } return null; };
  9. export const superpowersValidator = (control: AbstractControl) "' { const invisibility

    = control.get('invisibility'); const fly = control.get('fly'); const healing = control.get('healing'); const nightVision = control.get('nightVision'); const fields = [invisibility, fly, healing, nightVision] .filter(field "' field.value ""( true); if (fields.length < 2) { return { atleasttwo: true }; } return null; };
  10. export const superpowersValidator = (control: AbstractControl) "' { const invisibility

    = control.get('invisibility'); const fly = control.get('fly'); const healing = control.get('healing'); const nightVision = control.get('nightVision'); const fields = [invisibility, fly, healing, nightVision] .filter(field "' field.value ""( true); if (fields.length < 2) { return { atleasttwo: true }; } return null; };
  11. export const superpowersValidator = (control: AbstractControl) "' { const invisibility

    = control.get('invisibility'); const fly = control.get('fly'); const healing = control.get('healing'); const nightVision = control.get('nightVision'); const fields = [invisibility, fly, healing, nightVision] .filter(field "' field.value ""( true); if (fields.length < 2) { return { atleasttwo: true }; } return null; };
  12. @Component({ selector: '…', templateUrl: '…', providers: [ { provide: NG_VALUE_ACCESSOR,

    useExisting: forwardRef(() "' DistributorComponent), multi: true } ] }) export class DistributorComponent implements ControlValueAccessor {}
  13. @Component({ selector: '…', templateUrl: '…', providers: [ { provide: NG_VALUE_ACCESSOR,

    useExisting: forwardRef(() "' DistributorComponent), multi: true } ] }) export class DistributorComponent implements ControlValueAccessor {}
  14. points: number; writeValue(value: number): void { if (value "") undefined)

    { this.points = value; } } registerOnChange(fn: any): void { this.propagateChange = fn; } propagateChange = (_: any) "' {}; registerOnTouched(fn: any): void {} setDisabledState?(isDisabled: boolean): void {}
  15. increment() { this.points += 1; this.propagateChange(this.points); this.update.emit(this.groupPoints - 1); }

    decrement() { this.points -= 1; this.propagateChange(this.points); this.update.emit(this.groupPoints + 1); }
  16. increment() { this.points += 1; this.propagateChange(this.points); this.update.emit(this.groupPoints - 1); }

    decrement() { this.points -= 1; this.propagateChange(this.points); this.update.emit(this.groupPoints + 1); }
  17. this.skills$ = this.skills .valueChanges .subscribe(skills "' { let sum =

    ""*; this.points = 10 - sum; }); this.skills$.unsubscribe();
  18. T akeaways Pick up the one that works best for

    each situation Reuse controls
  19. T akeaways Pick up the one that works best for

    each situation Reuse controls Embrace Observables