angular-forms – Stepan Suvorov Blog https://stepansuvorov.com/blog Release 2.0 Thu, 23 May 2019 15:06:25 +0000 en-US hourly 1 https://wordpress.org/?v=6.3.1 Формы и валидация данных в Angular https://stepansuvorov.com/blog/2017/07/angular-forms-and-validation/ https://stepansuvorov.com/blog/2017/07/angular-forms-and-validation/#comments Sat, 01 Jul 2017 14:27:40 +0000 http://stepansuvorov.com/blog/?p=3382 Continue reading ]]> В отличии от AngularJS в Angular сделали целый модуль, который помогает в обработке форм.

Angular предлагает 2 подхода работы с формами:

  • основанный на шаблонах (template-driven)
  • реактивный (reactive)

Шаблонный более традиционный для декларативного подхода фреймворка. Реактивный появился позже и считается более прогрессивным и гибким. Мы разберем оба подхода.

Подключение модуля форм

Для начала работы с формами необходимо подключить модуль форм(FormsModule):

import { FormsModule } from '@angular/forms';

если мы хотим работать в реактивном подходе, то подключаем модуль ReactiveFormsModule:

import { ReactiveFormsModule } from '@angular/forms';

И конечно импортируем их в наш основной модуль:

View the code on Gist.

Шаблоно-ориентированный подход (template-driven)

В шаблонно ориентированном подходе мы по большей части оперируем 3мя сущностями: ngModel, ngModelGroup и ngForm.

ngModel

Чтобы привязать данные к элементу формы мы можем поставить директиву ngModel:

<input type="text" [ngModel]="name">

Есть 3 способа как получить введенные данные:

  • двухстороннее связывание
  • обработку события изменения
  • ссылку на элемент (либо ngModel)

ngModel и двухстороннее связывание (two way binding)

Способ, который пришел из AngularJs и в Angular практически не используется, но тем не менее, его хорошо знать:

<input type="text" [(ngModel)]="name">

то есть вы используете специальный синтаксис двойных скобок: сначала прямоугольные, затем круглые ( чтобы было проще запомнить последовательность используется подсказка “коробка с бананами” )

Теперь при вводе данных в элемент формы у нас будет обновляться и свойство контроллера name.

ngModel и обработка события

Вы можете использовать как родное событие поля ввода, например: для type text это будет input:

<input type="checkbox" [ngModel]="name" (input)="name = $event.target.value">

так и использовать специальное событие ngModelChange:

<input type="text" [ngModel]="name" (ngModelChange)="name = $event">

ngModel и обращение по ссылке

Чтобы поставить ссылку на ngModel, мы делаем следующее:

<input type="text" [ngModel]="name" #name>

теперь мы можем обратиться в шаблоне к значению свойства элемента:

{{name.value}}

либо в контроллере компонента через специальный декоратор ViewChild:

View the code on Gist.

Также мы можем сделать ссылку не только на элемент, но и на сам контроллер ngModel:

<input type="text" [ngModel]="name" #nameModel="ngModel">

Теперь в nameModel нам доступно не только значение модели, но и все дополнительные свойства и методы контроллера модели:

nameModel.valid

Валидация данных в шаблонном подходе

Полностью(или почти полностью) поддерживаются HTML5 валидация. То есть, например, если проставить полю атрибут require, то Angular его подхватит.

Свои валидаторы в шаблонном подходе

Не самый очевидный способ предлагают нам разработчики ангуляра для того, чтобы расширить валидаторы в шаблонном подходе. Мы должны создать директиву, в которой переопределить набор стантартных валидаторов NG_VALIDATORS, точнее дополнить своим(своими) с помощью флага multi:

View the code on Gist.

таким образом мы создали свой валидатор, который проверит не является ли значение равным ‘3’. Плюс попрошу обратить ваше внимание на селектор для директивы мы указали не только сам атрибут имени директивы, но также что на элементе будет присутствовать ngModel.

Свои асинхронные валидаторы в шаблонном подходе

Полностью идентичны синхронным, отличие только в том что ваш метод валидации возвращает Promise либо Observable, а прописывается не в NG_VALIDATORS, в а NG_ASYNC_VALIDATORS:

View the code on Gist.

Вывод ошибок

Чтобы вывести ошибки также можем обратиться к контроллеру ngModel по ссылке и получить его свойство errors:

{{nameModel.errors | json}}

.

…и теперь…

.

Реактивный (reactive) подход

Реактивном подходе мы настраиваем элементы формы не в шаблоне, а в контроллере, оперируя при этом следующими понятиями: FormControl, FormGroup, FormArray, FormBuilder.

На каждый элемент формы создается(вручную или автоматически) свой FormControl.

FormControl

Чтобы создать FormControl мы определяем свойство в контроллере компонента:

name: FormControl = new FormControl('Alice');

и привязываем его к конкретному элементу в шаблоне:

<input type="text" [formControl]="name">

После чего в контроллере мы можем подписаться на изменения:

this.name.valueChanges.subscribe(console.log)

Либо на изменения статуса(валидности):

this.name.statusChanges.subscribe(console.log)
Также можно получать статические значения (не подписываясь):
this.name.value
this.name.valid
 Полный список свойств можно посмотреть в описании AbstractControl (от которого наследуется FromControl)

FormGroup

FormGroup помогает удобно группировать контролы. Например: если мы хотим задавать не просто имя, а полное имя, содержащее само имя и фамилию:

View the code on Gist.

и подключаем в шаблоне:

View the code on Gist.

Обратите внимание, что для контролов обернутых в formGroup мы уже ставим formControlName свойство (а не [formControl]), которое будет указывать на то, где брать контрол в группе.

FormArray

FormArray прекрасно подойдет тогда, когда в форме у вас используется список, в который вы можете добавлять элементы. Давайте сделаем форму “учасников”, которая содержит список участников:

View the code on Gist.

и в шаблоне это будет выглядеть так:

View the code on Gist.

как видите мы выводим список контролов используя итератор(index) как имя контрола(formControlName) в списке.

Давайте добавим возможность добавления участников:

View the code on Gist.

и для этого в контроллере компонента определим 2 дополнительных метода removeUser и addUser:

View the code on Gist.

В итоге получим:

FormBuilder

Упростить процесс создания новых форм нам помогает сервис FormBuilder. Который мы можем инжектировать в контроллер:

View the code on Gist.

После чего создать туже форму (“учасники”), только теперь с помощью сервиса:

View the code on Gist.

вы можете сказать, что кода не стало меньше. Да, это так. FormBuilder имеет смысл использовать только для сложных форм с большим динамическим количеством контролов.

Валидация данных в реактивном подходе

Чтобы добавить валидатор на контрол мы всего лишь добавляем второй параметр, который может быть как одним валидатором, так и массивом(применяем разные проверки):

name: FormControl = new FormControl('Alice', [Validators.required]);

предварительно импортировав коллекцию валидаторов:

import { Validators } from “@angular/forms”;

Мы можем задавать один и больше валидатор. На данный момент в коллекции есть следующие валидаторы:

  • min
  • max
  • required
  • requiredTrue
  • email
  • minLength
  • maxLength
  • pattern

Создание своих валидаторов

Валидатор представляет из себя простую функцию, которая возвращает либо объект ошибки либо null:

View the code on Gist.

добавляется вторым параметром в контрол( вместе со стандартными валидаторами):

name: FormControl = new FormControl('Alice', [Validators.required, myNameValidator]);

В реальных проектах валидаторы собирают в группы заворачивают в классы и делают статическими методами классов.

Валидаторы с параметрами

Для создания валидаторов с параметрамми нам всего лишь необходимо завернуть нашу функцию валидатор в еще одну функцию, которая создаст замыкание для хранения параметров:

View the code on Gist.

Асинхронные валидаторы

Асинхронные валидаторы отличаются от синхронных только тем, что возвращают не статические данные, а Observable либо Promise:

View the code on Gist.

и также определяются 3-м параметром в конструкторе контрола:

name: FormControl = new FormControl('Alice', [myNameValidator], [myAsyncNameValidator]);

Вывод ошибок

Ошибки контрола хранятся в свойстве errors:

this.name.errors

Чтобы сделать какие-то действия в случае появления ошибок, можем написать так: добавив фильтры на изменение состояния и собственно валидность данных:

View the code on Gist.

Свойство есть не только у обычного контрола, но так же и у FormGroup, поэтому вы можете получить объект со всеми ошибками формы:

this.participantsForm.errors

Создание кастомных контроллов

Решил вынести эту главу в отдельный пост.

]]>
https://stepansuvorov.com/blog/2017/07/angular-forms-and-validation/feed/ 5
ng-nl 2017. brief review https://stepansuvorov.com/blog/2017/03/ng-nl-2017-brief-review/ https://stepansuvorov.com/blog/2017/03/ng-nl-2017-brief-review/#comments Thu, 16 Mar 2017 23:32:05 +0000 http://stepansuvorov.com/blog/?p=3299 Continue reading ]]>

Already like a good tradition I visited ng-nl conference (ng-nl 2015, ng-nl 2016).

Same as previous year it was great place and awesome people around.

But this time they really messed up with the schedule. I expected to have order of the topics that is provided on official web site, but appeared that it’s not actual and I had to follow the app one, basically the only place. And the app was lagging :(

Strange that this year I did not see anybody from the core Angular team. Also no old good Pascal Precht and Tero Parviainen in the list. At least we had good presentation by Todd Motto about Reactive Forms and really inspiring GraphQL talk by Uri Goldshtein.

…Instead of a keynote it was a talk…

Angular’s Reactive Forms by Todd Motto (code, video)

It was the same talk that Todd gave on ng-be. (see ng-be 2016 brief review). But today he was in a hurry to present all the materials and did not really keep the focus of audience. It might be some difficulties with understanding for developers who did not try Angular Forms before.

Good part comparing to ng-be talk was general architectural overview and going deep into real code from the high level.

some Q&A:

  • automatic generation HTML(not to duplicate form-model description twice)
    • no solution for now
  • good example of structural directive and dynamic component
    • structural directive – reimplementation of ngFor is pretty nice one
    • dynamic component – wizard or toster concepts
  • opinion about Augury
    • did not have time for it. Working hard on the course.

Demystifying Ahead-Of-Time compilation in Angular by Wassim Cheghamslides, video)

Quick intro about JIT.

JIT bad points

  • bundle size
  • perfomance
  • bootstrapping
  • security

AOT generates VM friendly code, but needs context, and context is provided by ngModules.

some words about Tree Shaking (30-60% less code)

So good points about AOT:

  • no security eval issue
  • faster time to interaction
  • smaller vendor bundle size

Easy use with angular-cli:

ng build --aot

Problems to make code “AOT ready”

  • lambda expression (must be export )
  • access modifiers (template properties should be public)
  • no variable exports

Q&A:

  • security: looking for interesting compiler injection examples
    • don’t know any, but evals are always evil.
  • bundle size: AOT makes only vendor part smaller, but your app code became bigger
    • yes, that was mentioned with asterisk on the slides
  • angular universal: what’s the status?
    • now SSR is part of ng4, but Angular Universal still exists like something bigger. We are working on different server rendering engines right now. Current implementation is on express. We would love to get as much feedback as possible from real projects.

Building a dynamic SPA with Angular by Filip Bech-Larsen (slides, video)

It was creasy talk about wrong way of doing things in Angular and reinventing own wheel.

So general, about everything…

about aot, about ssr…

need to review the video and return back to you with more details. for now have unstructured mess in my mind.

Addicted to AngularJS by Pete Bacon Darwin and George Kalpakas (video)

What’s wrong with AngularJs?

  • scaling to large teams
  • scaling to large applications
  • different platforms are not supported

Why not just go Angular right away

  • apps are really large
  • a lot of 3rd party dependancies
  • code base is large (other projects also on AngularJs as well)

ngUpgrade, steps to go:

  • correct structure with typescript
  • bootstrapping
  • downgrading components (so you create new components in Angular style but downgrade to AngularJs to make it work all together inside one app )
  • downgrading services
  • upgrade components (it works with AOT!!!)
  • upgrade services
  • rewrite all to Angular

Future

  • lazy loading
  • better testing story
  • better dual-router story
  • less boilerplate (better compiler integration + tooling)
  • better docs and examples

Q&A with George:

  • Is ngUpgrade for upgrading old components fixes templates as well?
    • Yes
  • Seriously?!
    • Yes.
  • So we will be able to run AOT for old components?!
    • Yes!

ACME (Angular CLI to Manage Everything) by David Müllerchen (code, video)

Funny Lego story about about Angular CLI and back to command line running all the commands one by one:

npm i -g @angular/cil
ng new ng-nl-demo --routing
cd ng-nl-demo
ng serve

Also code generation

ng g component hi-nl
ng g module foo

…and runinng on diffrent environments.

Could be handy for newbies, but for people who already tried angular-cli quite a boring talk.

Q&A:

  • Do you know about any plans to have 3rd party module installation via angular-cli (like ng install angular-material)
    • Don’t know.
  • Same about libraries. It would be really convenient to see environment ready for library creation.
    • Don’t know.

Component based API for your Angular Components with GraphQL by Uri Goldshtein (videos)

Why not REST:

  • lots of calls
  • lots of nested unneeded data

Key points:

  • it’s only single request, and no useless overfetching.
  • Schema to describe data/request structure.
  • nice tool to check our graphQL requests
  • some documentation on Angular Cookbook.
  • Apollo Client chrome extension.
  • easy to use with angular. (Example are coming…)
  • the way to synchronise the state
  • Any backend – Any client – Any language.

Improving Startup Performance with Lazy Loading in Angular by Manfred Steyer ( code , video )

I’ve already saw this talk on ng-be, so I decided to go to workshop instead.

Strictly recommend you to watch part about preloading of lazy modules.

 

Workshop: Maxim Salnikov – Progressive Web  Apps using the Angular Mobile Toolkit

It was just a disaster for audience and for Maxim. He prepared such a great workshop, but to do it in a proper way we would need 4-6 hours, but had to manage to finish in about 30 minutes.

You can check here detailed step-by-step description of the workshop.

 

Breaking Bias by Joy Eamesvideo )

Nothing todo with Angular, just talk about psychology and our stereotypes/biases

  • difference between tables

these 2 tetragons have the same sides!

 

 

]]>
https://stepansuvorov.com/blog/2017/03/ng-nl-2017-brief-review/feed/ 1