Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Sweet Angular, good forms never felt so good
Search
Ciro Nunes
August 02, 2017
Technology
320
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Sweet Angular, good forms never felt so good
Ciro Nunes
August 02, 2017
More Decks by Ciro Nunes
See All by Ciro Nunes
Rust Front-end with Yew
cironunes
0
98
Type safe CSS with Reason
cironunes
0
150
What I've learned building automated docs for Ansarada's design system
cironunes
0
100
Beyond ng new
cironunes
2
250
Animate your Angular apps
cironunes
0
460
Sweet Angular, good forms never felt so good
cironunes
0
110
Progressive Angular apps
cironunes
3
950
Angular: Um framework. Mobile & desktop.
cironunes
1
610
Firebase & Angular
cironunes
0
310
Other Decks in Technology
See All in Technology
RelayerというPHPのフレームワークを作った
polidog
PRO
0
140
OpenID for Verifiable Credentials 実装から見えた相互運用性確保までの道のり(OAuth/OIDC Numa (Immersion) Workshop 2026)
oidfj
PRO
0
300
EUDIWの枠組みを出発点に民間エコシステムの在り方を考える(OAuth/OIDC Numa (Immersion) Workshop 2026)
oidfj
PRO
0
290
[ホンマでっか SRE] あなたはなぜ SRE に?
_awache
0
260
All About Sansan – for New Global Engineers
sansan33
PRO
1
1.5k
カーネルまで探検して理解するふたつの自動計装
sumiyae
0
320
AI for Science時代を切り開く、政府の次世代HPC戦略の展望
gpuunite_official
0
260
markdown-poster Introduction
kazamori
0
200
Windows の互換機能 - 古いプログラムはなぜ動作できるのか
murachiakira
PRO
0
110
LLMアプリ、 雰囲気で運用してませんか? 〜LLMOpsの現在地〜
taka_aki
1
110
AIで変わるエンジニアの働き方(仮)
naoinaoi
0
560
tamachi.go 誕生の裏側
rymiyamoto
1
210
Featured
See All Featured
Google's AI Overviews - The New Search
badams
0
1.1k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
310
Raft: Consensus for Rubyists
vanstee
141
7.6k
Making the Leap to Tech Lead
cromwellryan
135
10k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
2.5k
How to make the Groovebox
asonas
2
2.3k
Deep Space Network (abreviated)
tonyrice
0
270
Thoughts on Productivity
jonyablonski
76
5.3k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
Making Projects Easy
brettharned
120
6.7k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
53k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.8k
Transcript
Sweet Angular good forms, never felt so good
@cironunesdev
None
None
Fill
Fill React
Fill React Validate
Fill React Validate Submit
None
Template-driven
Template-driven Model-driven (reactive)
Template-driven
None
FormsModule
[(ngModel)] FormsModule
[(ngModel)] #tpl reference variables FormsModule
import { NgModule } from '@angular/core'; import { BrowserModule }
from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; @NgModule({ imports: [ BrowserModule, FormsModule ] }) export class AppModule {}
None
model = { name: '' };
<form #heroForm="ngForm"> <input type="text" [(ngModel)]="model.name" name="name"> {{ model.name }} </form>
model = { name: '' };
<form #heroForm="ngForm"> <input type="text" [(ngModel)]="model.name" name="name" #name="ngModel"> <div [hidden]="name.valid ||
name.pristine">Invalid! </div> </form>
Model-driven (reactive)
None
ReactiveFormsModule
FormGroup, FormControl, FormArray, FormBuilder ReactiveFormsModule
import { NgModule } from '@angular/core'; import { BrowserModule }
from '@angular/platform-browser'; import { ReactiveFormsModule } from '@angular/forms'; @NgModule({ imports: [ BrowserModule, ReactiveFormsModule ] }) export class AppModule {}
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: [] }); }
<div class="form-group form-group --big"> <input placeholder="Name *" formControlName="name"> <div *ngIf="heroForm.get('name').touched
&& heroForm.get('name').hasError('required')" > Name is <strong>required </strong> </div> <div *ngIf="heroForm.get('name').touched && heroForm.get('name').hasError('minlength')" > The min length for the name is <strong>3 </strong> </div> </div>
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: [] }); }
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; };
Not covered
Not covered Custom controls
Not covered Custom controls Async validators
Not covered Custom controls Async validators Dynamic forms
T akeaways
T akeaways Both styles can be used in the same
app
T akeaways Both styles can be used in the same
app Pick up the one that works the best for each situation
T akeaways Both styles can be used in the same
app Pick up the one that works the best for each situation Embrace Observables
github.com/cironunes/good-forms
Thanks! @cironunesdev