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
89
Type safe CSS with Reason
cironunes
0
150
What I've learned building automated docs for Ansarada's design system
cironunes
0
98
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
AI-DLCを “そのまま導入しなかった”話 ~組織に合わせてアジャストした 私たちの実践共有~
hiroramos4
PRO
1
430
2026 AI Memory Architecture
nagatsu
0
310
Oracle Cloud Infrastructure:2026年6月度サービス・アップデート
oracle4engineer
PRO
0
330
コミュニティの有益性 ~JAWS Days 2026 での体験を通して~ / The Benefits of a Community ~Through My Experience at JAWS Days 2026~
seike460
PRO
0
270
SteampipeとExcel Power QueryでAWS構成定義書の作成を自動化する
jhashimoto
0
180
Microsoft のサポートとフィードバック総まとめ
murachiakira
PRO
0
110
螺旋型キャリアの生存戦略 / kinoko-conf2026
rakus_dev
1
1k
脱SaaS!FDEを支えるプロビジョニングと分離設計
knih
0
300
[AWS Summit Japan 2026]迷っているあなたへ_小さな一歩が、やがて自分を助けてくれる
sh_fk2
2
420
飲食店もAIで。レジ締めやハンディシステムをつくってる話 / Using AI for restaurant management
vtryo
0
180
From Prompt Engineering to Loop Engineering
shibuiwilliam
1
230
「ビジネスがわかるエンジニア」とは何か?
ryooob
0
320
Featured
See All Featured
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.8k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
450
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
280
Technical Leadership for Architectural Decision Making
baasie
3
420
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Prompt Engineering for Job Search
mfonobong
0
350
Writing Fast Ruby
sferik
630
63k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
330
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
sira's awesome portfolio website redesign presentation
elsirapls
0
280
WCS-LA-2024
lcolladotor
0
650
RailsConf 2023
tenderlove
30
1.5k
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