angular formControl 验证器的触发相关问题记录

文章讲述了Angular中formControl的使用和验证机制,以及如何解决点击后才触发验证的问题。介绍了模板驱动表单在处理复杂需求,如自封装组件和不定长数组时的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

正常使用

formControl与验证器的正常使用:

<!-- formGroup -->
<form [formGroup]="editForm">
  <mat-form-field>
     <mat-label>名称</mat-label>
     <input [type]="'text'" formControlName='name' matInput required>
     <mat-error *ngIf="editForm.get('name').invalid&&(editForm.get('name').dirty||editForm.get('name').touched)">
        <span *ngIf="editForm.get(['name']).hasError('required')">该字段必填</span>
     </mat-error>
   </mat-form-field>
</form>

<!-- formControl -->
  <mat-form-field>
     <mat-label>名称</mat-label>
     <input [type]="'text'" [formControl]='name' matInput required>
     <mat-error *ngIf="name.invalid&&(name.dirty||name.touched)">
        <span *ngIf="name.hasError('required')">该字段必填</span>
     </mat-error>
   </mat-form-field>
import {FormBuilder, Validators} from "@angular/forms";

export class AppComponent{
// 使用formGroup
  editForm=this.fb.group({
    name:[null,[Validators.required]]
  })
// 或者使用formControl
  name=this.fb.control(null,[Validators.required])

  constructor(
    private fb: FormBuilder,
  ) {
  }
}

特殊需求与问题

问题1. 经观察发现,当且仅当用户点击页面输入框时,才触发表单控件的验证,如何不进行操作,立即触发表单验证?

// html文件不改动

import { OnInit } from '@angular/core';
import {FormBuilder, Validators} from "@angular/forms";

export class AppComponent implements OnInit{
// 使用formGroup
  editForm=this.fb.group({
    name:[null,[Validators.required]]
  })
// 或者使用formControl
  name=this.fb.control(null,[Validators.required])

  constructor(
    private fb: FormBuilder,
  ) {
  }

  ngOnInit(): void {
    // 使用formGroup
    const formControl=this.editForm.get('name')
    formControl.markAsTouched();
    formControl.updateValueAndValidity();

    // 或者使用formControl
    this.name.markAsTouched();
    this.name.updateValueAndValidity();
  }
}

问题2. 现有一需求,涉及自封装组件、模板、不定长数组、表单验证影响按钮等功能,其具体页面如下:
在这里插入图片描述
如何搭建页面满足该需求?

下面将给出一种解决方案:
在list的数据量较大,且item个数具有不确定性的情况下,考虑到前端页面性能,一般不考虑通过formBuilder创建一个formArray与HTML元素进行绑定,这时就需要引入一个新的概念——采用模板驱动表单的方式解决该复杂问题。
什么是模板驱动表单?将通过下面的代码进行简要说明

<!-- 单个表单验证器 -->
<input type="text" name="fieldOne"  [ngModel]="fieldOne">
<input type="text" name="fieldTwo"  ngModel>

<!-- 整个表单-->
<form #form="ngForm">
      <input type="text" name="firstField" [ngModel]="model.firstField">
</form>
@Component({
  selector: 'app-reactive',
})
export class myComponent {
  fieldOne='';
  model = {
    firstField: ''
  };
}

由代码可以看出,表单元素绑定的是普通的js变量而非一般的formControl,为区分各表单元素,必须给每个元素进行命名,并且在ngModel无绑定变量的时候仍需指明ngModel,更为详细的介绍可以参阅一位前辈的这篇文章:https://blog.youkuaiyun.com/Herishwater/article/details/105635514
回到正题,上文中我们提到的这种较为复杂的需求,我们该如何解决?下面是一种简要的解决方法:

<div>
  <button [disable]="myForm.invalid"></button>
  <form #myForm="ngForm">
      <my-list-component [data]="myList" [itemTemplateRef]='myTemplateRef'></my-list-component>
      <ng-template #myTemplateRef let-item let-index="index">
          <input name='field{{index}}'
                 #field="ngModel"
                 [(ngModel)]='item.field'
                 type='text'
                 required>
          <div *ngIf="field.invalid">field is required</div>
      </ng-template>
   </form>
</div>
<!-- 注意,即使是ng-template,也要被包含于form中,ngForm才能关联到input对应的ngModel-->
@Component({
  selector: 'app-reactive',
})
export class myComponent {
  myList=[
    {field:null},
    {field:null},
    {field:null},
    {field:null},
    {field:null},
  ]
}

其中自封装组件代码也简要给出

<!-- my-list-component -->
<div class="list">
  <div *ngFor="let item of data;let i = index" class="list-item">
      <ng-container *ngTemplateOutlet="itemTemplateRef context: {$implicit: item,index:i}"></ng-container>
  </div>
</div>
import { Component,Input, TemplateRef } from '@angular/core';

@Component({
  selector: 'my-list-component',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.scss']
})
export class ListComponent implements OnChanges {
  @Input()
  itemTemplateRef: TemplateRef<any>;
  @Input()
  data: any[] = []
}

至此,又一问题得到解决。

后续问题,等待更新…

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值