文章目录
Shark用得过于熟练,却不大了解的ng表单,在使用shark的过程中产生了以下一些疑问。
一、[ngModelOptions]="{standalone: true}" 是什么意思?为什么在我们的项目中使用ngModel的时候需要用到?
<shark-select [(ngModel)]="channelId" [data]="channelList"></shark-select>
在表单中直接这么写会报错
ChannelListComponent.html:13 ERROR Error: If ngModel is used within a form tag, either the name attribute must be set or the form
control must be defined as ‘standalone’ in ngModelOptions.
Example 1: <input [(ngModel)]=“person.firstName” name=“first”>
Example 2: <input [(ngModel)]=“person.firstName” [ngModelOptions]="{standalone: true}">
再看下ngModelOptions
的定义,它其实是ngmodel
指定的一个input属性,当standalone值为true时,代表着此 ngModel 不会把自己注册进它的父表单中,其行为就像没在表单中一样。
我们项目中使用ngModel其实是属于Template-driven Form,但shark中其实并没有用到ng的form表单校验。而Angular 会在 <form>
标签上自动创建并附加一个 NgForm 指令,NgForm 指令为 form 增补了一些额外特性。 它会控制那些带有 ngModel 指令和 name 属性的元素,监听他们的属性(包括其有效性)。 它还有自己的 valid 属性,这个属性只有在它包含的每个控件都有效时才是真。
forms/src/directives/ng_model.ts:
/**
* @description
* Tracks the name bound to the directive. The parent form
* uses this name as a key to retrieve this control's value.
*/
// TODO(issue/24571): remove '!'.
@Input() name !: string;
forms/src/directives/ng_form.ts:
/**
* @description
* Method that sets up the control directive in this group, re-calculates its value
* and validity, and adds the instance to the internal list of directives.
*
* @param dir The `NgModel` directive instance.
*/
addControl(dir: NgModel): void {
resolvedPromise.then(() => {
const container = this._findContainer(dir.path);
(dir as{control: FormControl}).control =
<FormControl>container.registerControl(dir.name, dir.control);
setUpControl(dir.control, dir);
dir.control.updateValueAndValidity({emitEvent: false});
this._directives.push(dir);
});
}
可以看到Angular 创建了一些 FormControl,并把它们注册到 Angular 附加到 <form>
标签上的 NgForm 指令。 注册每个 FormControl 时,使用name
属性值作为键值。
所以每个form中的input元素的name值必须是唯一的,或者使用[ngModelOptions]="{standalone: true}"
将其排除在表单之外。
那么ng表单和表单验证是什样的?
二、ng表单和表单验证 (https://angular.cn/guide/forms-overview)
ng中一个重要的概念就是表单,ng提供了响应式表单(Reactive Form)和模板驱动表单(Template-driven form)两种形式。这两种形式的表单都基于几个共同的底层概念:
- FormControl 实例用于追踪单个表单控件的值和验证状态。
- FormGroup 用于追踪一个表单控件组的值和状态。
- FormArray 用于追踪表单控件数组的值和状态。
- ControlValueAccessor 用于在 Angular 的 FormControl 实例和原生 DOM 元素之间创建一个桥梁。
2.1 目前Angular中提供的内置验证器有
class Validators {
static min(min: number)