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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
89
Type safe CSS with Reason
cironunes
0
150
What I've learned building automated docs for Ansarada's design system
cironunes
0
96
Beyond ng new
cironunes
2
240
Animate your Angular apps
cironunes
0
460
Sweet Angular, good forms never felt so good
cironunes
0
100
Progressive Angular apps
cironunes
3
940
Angular: Um framework. Mobile & desktop.
cironunes
1
610
Firebase & Angular
cironunes
0
300
Other Decks in Technology
See All in Technology
気軽に使える"情報のハブ"としてのNotion活用 〜フロー情報の集積点 と、 Claude Code × Notion AI〜
syucream
1
150
攻撃者視点で考えるDetection Engineering
cryptopeg
3
2k
Claude Codeをどのように キャッチアップしているか
oikon48
13
8.5k
LayerX コーポレートエンジニアリング室におけるサプライチェーンセキュリティへの取り組み / Supply Chain Security at LayerX Corporate Engineering
yuyatakeyama
2
670
サイバーエージェントにおけるAI推進戦略と変革への取り組み
shotatsuge
0
100
日本 Fintech 未来予測レポート 2027〜2028年(オリジナル版)
8maki
0
2.3k
気づかぬうちにセキュリティ負債を生むAPIキー運用
sgwrmctk
0
180
OTel × Datadog で 「AI活用」を計測し、改善に繋げる
shihochan
1
370
AIはどのように 組織のアジリティを変えるのか?
junki
4
1k
Agent Skills設計で柔軟性と硬さのバランスが難しい話
nassy20
0
140
日本 Fintech 未来予測レポート 2027〜2028年(手動編集版)
8maki
1
2.4k
あなたの知らないPDFのアクセシビリティ
lycorptech_jp
PRO
0
220
Featured
See All Featured
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.5k
The Curse of the Amulet
leimatthew05
1
13k
The Pragmatic Product Professional
lauravandoore
37
7.3k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
430
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5.9k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
160
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
610
Typedesign – Prime Four
hannesfritz
42
3.1k
Color Theory Basics | Prateek | Gurzu
gurzu
0
370
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
530
Claude Code のすすめ
schroneko
67
230k
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