[Angular] Forms - Introduction to form in Angular

前言

在前端领域中,使用表单处理用户输入是常见的操作,可以使用表格让使用者登录、输入信息以及其他数据输入的任务,Angular提供了两种通过表单处理用户输入的方法:reactivetemplate,这两种方法,此篇章将会介绍他们之间的差异与用途。

Choosing an approach

reactive与template以不同的方式处理表单讯息,他们拥有各自的优劣势:

  • Reactive:提供对地层表单物件直接且显性的访问,他的可扩充性、可重用性、可测试性都比template更高。
  • template:依赖template中的指令来建立和操作底层物件,很容易新增到应用中,适合用在非常基本的表单需求与逻辑。

Key differences

... Reactive template
建立表单模型 在class中建立 在template中建立
资料模型 不可变 可变
可预测性 同步 非同步
验证 function 指令

Setting up the form model

Reactive与Template都会追踪使用者互动的表单输入元素元件模型中的表单资料的变更,他们共用同一套底层模块,不同的是他们在建立和管理表单的方面不同。

Common form foundation classes

reactive和template都透过以下几本的class建立:

  • FormControl:追踪单个表单元件的值和验证状态。
  • FormGroup:追踪一个表单控制元件集合的值和状态。
  • FormArray:追踪一个阵列中表单控制元件的值和状态。
  • ControlValueAccessor:建立连接Angular FromControl与DOM的桥梁。

Setup in reactice forms

若要使用reactive forms,可以在Component中定义form model,[formControl]会使用internal value accessor将画面中特定表单元素与FormControl连接起来。

import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';

@Component({
  selector: 'app-reactive-favorite-color',
  template: `
    Favorite Color: <input type="text" [formControl]="favoriteColorControl">
  `
})
export class FavoriteColorComponent {
  favoriteColorControl = new FormControl('');
}

[formControl]指令将画面中的input元件与Component中的FormControl物件连接起来,换句话说当使用者在画面上的input中输入值,会透过[formControl]将使用者输入的值传递给Conponent中的FormControl物件。
https://ithelp.ithome.com.tw/upload/images/20201104/20124767nZNWWulKXR.png
(图片来源:Angular

Setup in template-driven forms

由於Template forms的表单形式是隐性的,所以所以需要透过NgModel来建立并管理FormControl。

import { Component } from '@angular/core';

@Component({
  selector: 'app-template-favorite-color',
  template: `
    Favorite Color: <input type="text" [(ngModel)]="favoriteColor">
  `
})
export class FavoriteColorComponent {
  favoriteColor = '';
}

在template form中,透过NgModel将使用者输入的数值连接到Component中的FormControl。
https://ithelp.ithome.com.tw/upload/images/20201104/20124767I5h14STnQc.png
(图片来源:Angular


Data flow in forms

Angular必须在我们使用form的时候将画面与Componet中的model保持同步,举例来说当使用者在画面中更改了表单中的资料时,新的值必须要立马反映在model中,同样的当model中的逻辑改变时,其结果也需要立即的反应在画面中,Reactive与Template在处理使用者或程序更改的方式有所不同。

Data flow in reactive forms

在reactive forms中,画面里的每一个表单元素都直接的连接到FormControl,画面与model的之间的数据更新是同步的,下图表示当画面更改元件中的数值时数据是如何流动到FromControl中。
https://ithelp.ithome.com.tw/upload/images/20201104/20124767nM0MOJMxp1.png
(图片来源:Angular

  1. 使用者在画面中的表单输入新的值。
  2. 画面中的表单元件发出带有最新数值的输入事件
  3. 画面中表单元件的Control Value Accessor会监听这个表单元件上的事件,并立即将新的值传递给Component中的FormControl。
  4. Component中的FormControl会透过valueChange这个可观察物件发送这个新的值给valueChange的订阅者。
  5. 所有valueChange的订阅者收到使用者输入的新值。

下图是介绍FormControl的值被更改後,如何将更改的值反映到画面中。
https://ithelp.ithome.com.tw/upload/images/20201104/20124767ycks8Ex7Xn.png
(图片来源:Angular

  1. 呼叫favoriteColorControl.setValue()来更新FormControl的值。
  2. FormControl透过valueChanges发出新值。
  3. valueChanges的订阅者会收到新值(画面中的input元件)。
  4. 画面input元件更新收到的新值。

Data flow in template-driven forms

在template forms中的每个表单元件都会连接到内部管理表单模型的指令。

下图说明了当更改画面元件後,更新的数值是如何流向model。
https://ithelp.ithome.com.tw/upload/images/20201104/20124767iwvCFPMhTN.png
(图片来源:Angular

  1. 使用者输入新值(blue)。
  2. input元件发出带有新值(blue)的输入事件。
  3. input元件触发FormContorl的setValue()方法来更新FormControl的值。
  4. FormControl透过valueChanges发出新值。
  5. valueChanges的订阅者收到新值。
  6. Control Value Accessory呼叫Model.viewModelUpdate(),发出一个ngModelChange事件。
  7. ngModelChange事件会修改Component中双向绑定的属性的值(this.favoriteColor)

下图说明当修改Component中的this.favoriteColor後,画面中的input表单是如何更新新值。
https://ithelp.ithome.com.tw/upload/images/20201104/20124767KbAXvasFXX.png
(图片来源:Angular

  1. Component中的this.favoriteColor更改了值(red)。
    --------- 变更检测开始 ---------
  2. Angular呼叫NgModel上的ngOnChanges方法。
  3. ngOnChange会将一个非同步更改FormControl值的任务放入伫列中。
    --------- 变更检测结束 ---------
  4. FormControl更新任务完成。
  5. FormControl透过valueChanges发出新值。
  6. valueChanges的订阅者收到新值。
  7. Control Value Accessor更新画面input元件中的值。

Mutability of the data model

  • Reactive:reactive forms透过不能改变的数据结构来保持数据行的单一化,当每一次触发更新时,FormControl都会return一个新的数据模型而不是更新现有的数据模型,这使变更检测更有效率,因为只需要在唯一性更改(物件参考发生变化)时进行更新。
  • Template:template forms依赖双向资料绑定,由於使用双向资料绑定时没有用来对资料模型进行追踪的唯一性更改,因此变更检测在需要确定何时更新时效率较低。

参考文献:Angular


<<:  JS 原始型别的包裹物件与原型的关联 DAY67

>>:  数据治理(Data Governance)

【Day 08】Sorting:Selection Sort 选择排序法 ( 用 JavaScript 学演算法 )

选择排序法的概念是,将阵列分为两个部分,每次扫描未排序的部分时,从数列中拿出最小的数,丢到另一边,...

大脑如何精准学习 (3) 错误回馈

「错误」的定义 重复上章节对「好奇心」的心理假设: 大脑只有在感知到预测和实际认知有缺口时,才会启动...

[FLM] 比较5.19 / 5.20 / 6.00 三者不同处

延续 https://ithelp.ithome.com.tw/articles/10261533...

Day 16 - 设定 PBR

我们今天要来设定 PBR,我们以 Juniper MX 为例 首先,我们要先决定一个 routing...

[Day14]资料表合并实做

在Day5的时候,主要介绍了SELECT语句,在当中也有提及多种资料表合并的语法,这篇文会列出一些简...