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
93
Type safe CSS with Reason
cironunes
0
150
What I've learned building automated docs for Ansarada's design system
cironunes
0
99
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
950
Angular: Um framework. Mobile & desktop.
cironunes
1
610
Firebase & Angular
cironunes
0
300
Other Decks in Technology
See All in Technology
“それは自分の仕事じゃない"を越えて行け
yuukiyo
1
490
CDKで書くECSのベストプラクティス、 改めて考え直す2026 #cdkconf2026
makies
3
850
AIと共生する開発者プラットフォーム:バクラクのモノレポ×マイクロサービス基盤
sakajunquality
2
4k
ゴールデンパスは敷いただけでは道にならない ─ 企画部門のエンジニアが技術標準を事業価値に変えるまで
mhrtech
1
230
SRE本の知られざる名シーン / The Hidden Gems of Google SRE Book
nari_ex
1
430
CSに"SLO"は要らない、経営層に"99.9%"は伝わらない - SREを全社に"翻訳"する3原則
cscengineer
PRO
1
5.2k
大量データに対しても、生成AIを用いてリーズナブルにデータ加工をしたい!Databricksのai_queryについて調べてみた
kamoshika
1
220
Making sense of Google’s agentic dev tools
glaforge
1
290
変更し続けられるシステムをどう保つか — AI時代のSSoTという設計原則
kawauso
1
240
Claude Code公式skillで 自分の仕事を少しずつ手放そう!(Claude Code開発ノウハウ大公開スペシャル by クラスメソッド)
kaym
1
500
第67回コンピュータビジョン勉強会CVPR2026読会前編
tsukamotokenji
0
150
SRE Next 2026 何でも屋からの脱却
bto
0
1k
Featured
See All Featured
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
220
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
500
Claude Code のすすめ
schroneko
67
230k
The Cost Of JavaScript in 2023
addyosmani
55
10k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
420
How GitHub (no longer) Works
holman
316
150k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
320
What does AI have to do with Human Rights?
axbom
PRO
1
2.3k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
ラッコキーワード サービス紹介資料
rakko
1
3.9M
So, you think you're a good person
axbom
PRO
2
2.1k
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