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
Data Hubグループ 紹介資料
sansan33
PRO
0
3.2k
Claude Codeで開発以外の業務も爆速化しよう!
minorun365
PRO
11
9k
Contract One Engineering Unit 紹介資料
sansan33
PRO
0
20k
ハッカソンで入賞した話 @ Findy LT
asari194617
0
1.5k
NANDでも描画したい!
nichica906
3
810
8bit CPU 2026
koba789
7
3k
VPCでもFloatingIPを使いたいんだ
y_kotani
1
130
1000⼈規模のClaude Enterprise運⽤を「Oktaのグループ」と「Slack」に集約する
sansantech
PRO
1
500
RapidCopy2 Matrix I/Oエンジンによるファイルコピーソフトウェアの設計と実装
kengosawa2
1
480
Claude Codeの体系的な理解と知識のフック
oikon48
8
6k
atproto spaces概要
yamarten
0
110
分割40%キーボードにスムーズに入門するには
hoto17296
1
180
Featured
See All Featured
BBQ
matthewcrist
89
10k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
390
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.9k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
400
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
480
GraphQLとの向き合い方2022年版
quramy
50
15k
Utilizing Notion as your number one productivity tool
mfonobong
4
560
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
380
We Are The Robots
honzajavorek
0
310
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