Angular表单

这篇具有很好参考价值的文章主要介绍了Angular表单。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

案例来源于Angular官网(略作拓展)

表单

1.1 响应式表单 reactive forms

通过指令[formControl]实现,直接访问FormControl实例

通过指令内部的值访问器ControlValueAccessor,将FormControl实例和视图中的表单元素联系起来。

1.2 模板驱动表单 template-driven forms

通过NgModel指令为表单元素创建并管理FormControl实例,间接访问FormControl实例

1.3 比较

响应式 模板驱动
建立表单模型 显式创建,在组件类里创建 隐式创建
数据模型 结构化、不可变 非结构化、可变
数据流 同步 异步
表单验证 函数 指令
适用场景 可伸缩性强、较少的测试设置(不需要深入理解变更检测) 可复用性弱、测试以来手动触发变更检测

1.4 使用

declare abstract class AbstractControl<TValue = any, TRawValue extends TValue = TValue> {
  readonly value: TValue;
  constructor(validators: ValidatorFn | ValidatorFn[] | null, asyncValidators: AsyncValidatorFn | AsyncValidatorFn[] | null);
  get valid(): boolean;
  readonly errors: ValidationErrors | null;
  readonly valueChanges: Observable<TValue>;
  addValidators(validators: ValidatorFn | ValidatorFn[]): void;
  removeValidators(validators: ValidatorFn | ValidatorFn[]): void;
  abstract setValue(value: TRawValue, options?: Object): void;
  abstract patchValue(value: TValue, options?: Object): void;
  abstract reset(value?: TValue, options?: Object): void;
  setErrors(errors: ValidationErrors | null, opts?: {
        emitEvent?: boolean;
    }): void;
  getError(errorCode: string, path?: Array<string | number> | string): any;
  hasError(errorCode: string, path?: Array<string | number> | string): boolean;
}

export declare interface FormControl<TValue = any> extends AbstractControl<TValue> {
  setValue(value: TValue, options?: {
      onlySelf?: boolean;
      emitEvent?: boolean;
      emitModelToViewChange?: boolean;
      emitViewToModelChange?: boolean;
  }): void;
  
  patchValue(value: TValue, options?: {
      onlySelf?: boolean;
      emitEvent?: boolean;
      emitModelToViewChange?: boolean;
      emitViewToModelChange?: boolean;
  }): void;
}

export export declare class FormGroup<TControl extends {
    [K in keyof TControl]: AbstractControl<any>;
} = any> extends AbstractControl<ɵTypedOrUntyped<TControl, ɵFormGroupValue<TControl>, any>, ɵTypedOrUntyped<TControl, ɵFormGroupRawValue<TControl>, any>> {
  
  controls: ɵTypedOrUntyped<TControl, TControl, {
        [key: string]: AbstractControl<any>;
    }>;
  
  addControl(this: FormGroup<{
        [key: string]: AbstractControl<any>;
    }>, name: string, control: AbstractControl, options?: {
        emitEvent?: boolean;
    }): void;
  
  removeControl(this: FormGroup<{
        [key: string]: AbstractControl<any>;
    }>, name: string, options?: {
        emitEvent?: boolean;
    }): void;
}

1.4.1 FormControl

创建表单/模板中注册表单
export class NameEditorComponent {
  name = new FormControl('', [Validators.required, this.lessThan8Words]);
}
<label for="name">Name: </label>
<input id="name" type="text" [formControl]="name">
获取/更新表单的值
<p>Value: {{ name.value }}</p>

<button type="button" (click)="updateName()">Update Name</button>
<button type="submit" (click)="getName()">Update Name</button>
updateName() {
  this.name.setValue('Nancy');
}

getName() {
  console.log(this.name.value);
}
为表单添加事件
ngOnInit(): void {
  this.name.valueChanges.subscribe((value) => {
    console.log(value); // 获取到最新的表单值
  });
}
校验表单

我们在创建表单时,为表单添加自定义校验规则(名字长度不能超过8个字母)

lessThan8Words: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
  if (control.value.length >= 8) {
    return { nameError: 'name length must less than 8.' };
  }
  return null;
};

name = new FormControl('', [Validators.required, this.lessThan8Words]);
<p *ngIf="name.hasError('nameError')" style="color: red;">{{ name.getError('nameError') }}</p>

name这个表单对象中,包含了以下几个和校验相关的常用属性

valid: boolean:表示是否符合校规则

errors:ValidationErrors:汇总了所有校验错误的属性和值

  • hasError('nameError')error对象是否包含该错误
  • getError('nameError'):获取该错误的错误信息
{
    "nameError": "name length must less than 8."
  	"required": true // 说明此时,表单里为空
}
代码
import { NgIf } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import {
  FormControl,
  ReactiveFormsModule,
  ValidationErrors,
  ValidatorFn,
  Validators,
  AbstractControl,
} from '@angular/forms';

@Component({
  standalone: true,
  selector: 'app-name-editor',
  templateUrl: './name-editor.component.html',
  styleUrls: ['./name-editor.component.css'],
  imports: [ReactiveFormsModule, NgIf],
})
export class NameEditorComponent implements OnInit {
  ngOnInit(): void {
    this.name.valueChanges.subscribe((value) => {
      console.log(value);
    });
  }

  lessThan8Words: ValidatorFn = (
    control: AbstractControl
  ): ValidationErrors | null => {
    if (control.value.length >= 8) {
      return { nameError: 'name length must less than 8.' };
    }
    return null;
  };

  name = new FormControl('', [Validators.required, this.lessThan8Words]);

  updateName() {
    this.name.setValue('Nancy');
  }

  getName() {
    console.log(this.name.value);
  }
}
<label for="name">Name: </label>
<input id="name" type="text" [formControl]="name">

<p>Value: {{ name.value }}</p>
<p *ngIf="name.hasError('nameError')" style="color: red;">{{ name.getError('nameError') }}</p>


<button type="button" (click)="updateName()">Update Name</button>
<button type="submit" (click)="getName()">Update Name</button>

表单中通常包含多个相关的控件,响应式表单提供了FormGroupFormArray两种组合相关控件的方式

1.4.2 FormGroup

FormGroup可以理解为FormControl的组合,在使用上略有延伸。此处我们来看几个不同的地方

创建表单/模板中注册表单
export class FullNameEditorComponent implements OnInit {
  fullNameForm = new FormGroup({
    firstName: new FormControl(''),
    lastName: new FormControl(''),
  });
}
<form [formGroup]="fullNameForm" (ngSubmit)="onSubmit()">
    <label for="first-name">First Name: </label>
    <input id="first-name" type="text" formControlName="firstName">

    <label for="last-name">Last Name: </label>
    <input id="last-name" type="text" formControlName="lastName">
</form>
获取/更新表单的值
public onSubmit(): void {
  console.log(this.fullNameForm?.value);
}
  • setValue:严格遵循表单的组织结构,替换控件的整个值。若传入对象的结构和定义的表单结构不同,则更新失败。
  • patchValue:替换表单中的任何属性。若传入对象的结构和定义的表单结构不同,不报错,仅更新表单模型中定义的属性。
public updateFullName(): void {
  this.fullNameForm.setValue({ firstName: 'amy', lastName: 'niu' });
  this.fullNameForm.patchValue({ firstName: 'amy' }); // 这种也能通过
}
新增/移除表单
this.fullNameForm.addControl('newControl', new FormControl(''));
this.fullNameForm.removeControl('firstName');

获取到某个FormControl对象

  • controls

    {
      firstName: FormControl,
      lastName: FormControl
    }
    
  • get('firstName')获取到firstName这个FormControl对象

1.4.3 FormArray

FormArray可以理解为FormControl的数组,在使用上略有延伸。

  • 构造函数的第一个参数即是FormControl的数组
  • 使用方式类似Array,at/push/insert等

1.4.3 FormBuilder

当我们要设计一个控件众多的表单时,重复的new FormControl非常麻烦,所以FormBuilder提供了更便利的方式生成控件。

this.formBuilder.group的返回值是FormGroup类型,故它的具体使用方式和`FromGroup基本一致,此处不重复阐述。

仅展示如何创建表单以及在模版中注册表单文章来源地址https://www.toymoban.com/news/detail-845313.html

import { JsonPipe, NgFor } from '@angular/common';
import { Component } from '@angular/core';
import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Validators } from '@angular/forms';
import { FormArray } from '@angular/forms';

@Component({
  standalone: true,
  selector: 'app-profile-editor',
  templateUrl: './profile-editor.component.html',
  styleUrls: ['./profile-editor.component.css'],
  imports: [NgFor, ReactiveFormsModule, JsonPipe],
})
export class ProfileEditorComponent {
  profileForm = this.formBuilder.group({
    firstName: ['', Validators.required],
    lastName: [''],
    address: this.formBuilder.group({
      street: [''],
      city: [''],
      state: [''],
      zip: [''],
    }),
    aliases: this.formBuilder.array([this.formBuilder.control('')]),
  });

  get aliases() {
    return this.profileForm.get('aliases') as FormArray;
  }

  constructor(private formBuilder: FormBuilder) {}

  addAlias() {
    this.aliases.push(this.formBuilder.control(''));
  }

  onSubmit() {
    // TODO: Use EventEmitter with form value
    console.warn(this.profileForm.value);
  }
}

<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
  <label for="first-name">First Name: </label>
  <input id="first-name" type="text" formControlName="firstName" required>

  <label for="last-name">Last Name: </label>
  <input id="last-name" type="text" formControlName="lastName">

  <div formGroupName="address">
    <h2>Address</h2>

    <label for="street">Street: </label>
    <input id="street" type="text" formControlName="street">

    <label for="city">City: </label>
    <input id="city" type="text" formControlName="city">

    <label for="state">State: </label>
    <input id="state" type="text" formControlName="state">

    <label for="zip">Zip Code: </label>
    <input id="zip"type="text" formControlName="zip">
  </div>

  <div formArrayName="aliases">
    <h2>Aliases</h2>
    <button type="button" (click)="addAlias()">+ Add another alias</button>

    <div *ngFor="let alias of aliases.controls; let i=index">
      <!-- The repeated alias template -->
      <label for="alias-{{ i }}">Alias:</label>
      <input id="alias-{{ i }}" type="text" [formControlName]="i">
    </div>
  </div>


  <p>Complete the form to enable button.</p>
  <button type="submit" [disabled]="!profileForm.valid">Submit</button>
</form>

<hr>

<p>Form Value: {{ profileForm.value | json }}</p>

<p>Form Status: {{ profileForm.status }}</p>

<button type="button" (click)="updateProfile()">Update Profile</button>

到了这里,关于Angular表单的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Angular表单

    案例来源于Angular官网(略作拓展) 通过指令 [formControl] 实现,直接访问 FormControl 实例 通过指令内部的值访问器 ControlValueAccessor ,将 FormControl 实例和视图中的表单元素联系起来。 通过 NgModel 指令为表单元素创建并管理 FormControl 实例,间接访问 FormControl 实例 响应式 模板驱

    2024年04月09日
    浏览(48)
  • angular表单的一些概念和方法

    UntypedFormGroup UntypedFormGroup 是一个类型安全的 FormGroup,它是一个表单控件容器,用于组织和管理一组表单控件 markAsPristine()  方法用于将 FormGroup 标记为 “pristine”(未修改)状态。这意味着表单控件的值没有被修改过。通常在表单提交后或者在重置表单时使用该方法来重置表

    2024年02月15日
    浏览(40)
  • 大型医院云HIS系统:采用前后端分离架构,前端由Angular语言、JavaScript开发;后端使用Java语言开发 融合B/S版电子病历系统

    一套医院云his系统源码 采用前后端分离架构,前端由Angular语言、JavaScript开发;后端使用Java语言开发。融合B/S版电子病历系统,支持电子病历四级,HIS与电子病历系统均拥有自主知识产权。 文末卡片获取联系! 基于云计算技术的B/S架构的医院管理系统(简称云HIS),采用前后

    2024年02月03日
    浏览(48)
  • Angular中RxJS处理一些任务——HTTP请求,表单处理

            此篇是完善https://blog.csdn.net/qq_44327851/article/details/134917018这篇博客,在上篇博客中我们提到了处理异步数据流,那在Angular中有哪些异步数据流呢,又是如何处理的呢?         Angular中的RxJS是一个非常强大和流行的库, 用于处理异步数据流和事件流 。它提供了丰

    2024年02月03日
    浏览(47)
  • angular前端环境搭建、安装angular

    1.下载node.js安装包(要求node版本大于12.20) Node.js官方网站 : https://nodejs.org/en/ 进入官网后,当前页面下载的是最新版本,如需要下载历史版本,点击红框标注的其他下载,在进入的新的页面底部,选择红框标准的先前版本,然后下载相应的版本,在跳转的页面下载win64的版

    2024年02月03日
    浏览(56)
  • 如何在 Angular 中为响应式表单创建自定义验证器

    简介 Angular 的 @angular/forms 包提供了一个 Validators 类,支持诸如 required 、 minLength 、 maxLength 和 pattern 等有用的内置验证器。然而,可能存在需要更复杂或自定义规则进行验证的表单字段。在这种情况下,您可以使用自定义验证器。 在 Angular 中使用响应式表单时,您可以使用函

    2024年02月22日
    浏览(49)
  • angular中多层嵌套结构的表单如何处理回显问题

    最近在处理angular表单时,有一个4层结构的表单。而且很多元素时动态生成,如下: 其界面表现如下: 、 而在编辑的状态时如何根据后端返回数据结构进行回显。angular中formbuilder对象提供了setValue和patchValue两个方法。这两个方法只对一层对象有效,对于多层嵌套的数据结构

    2024年02月09日
    浏览(39)
  • angular框架简介基础与使用(全文2w8字)前端框架angular

    本文的所有内容,可以在我的博客上看到,下面是地址。建议去博客看,因为csdn的这篇图片我没上传。 可以转载,但请注明出处 我的博客—点击跳转 https://numb.run Angular是谷歌开发的一款开源的web前端框架,诞生于2009年,由Misko Hevery 等人创建,后为Google所收购。是一款优秀

    2024年02月02日
    浏览(42)
  • Angular:引领未来的前端框架

    Angular是一款由Google开发的强大前端框架,具有丰富的特性和卓越的性能。本文将介绍Angular的基本概念、特点、应用场景以及与其他框架的对比。 一、引言 随着Web应用程序的日益复杂,前端框架在开发过程中扮演着越来越重要的角色。Angular作为一款由Google主导的前端框架,

    2024年01月22日
    浏览(43)
  • 2023.07.07面试偏前端angular

    ==和===是JavaScript中的两个比较运算符,用于比较两个值的相等性。 ==是松散相等运算符,它会进行类型转换后再比较值是否相等。如果两个值的类型不同,==会尝试将它们转换为相同的类型,然后再进行比较。例如,1 == \\\'1\\\'会返回true,因为它们在进行比较之前会被转换为相同

    2024年02月13日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包