Angular의 반응형 양식에 대한 간략한 분석

青灯夜游
풀어 주다: 2022-04-25 10:26:40
앞으로
3356명이 탐색했습니다.

이 글에서는 Angular의 반응형 폼에 대해 설명하고, 예제를 통해 간단한 폼 구현 방법을 소개하겠습니다. 모두에게 도움이 되길 바랍니다!

Angular의 반응형 양식에 대한 간략한 분석

최근 회사 프레임워크 업그레이드로 인해 기존의 양식을 수동으로 확인하는 방식을 버리고 모든 양식을 반응형으로 변경했습니다. 한번도 사용해본 적이 없어서 처음에는 나만 그런 줄 알았습니다. 그룹을 이해하고 나니 다른 동료들은 대부분 익숙하지 않다는 걸 알게 되었어요

나중에 시간이 촉박해서 하면서 배우고 변화할 수밖에 없어서 어쩔 수 없었어요. 물론, 공부도 좀 하긴 했지만, 익숙하신 분들에게는 아주 간단할 수도 있지만, 학습 과정과 요약을 정리하자면 일종의 정리입니다. 문제를 해결하는 방법도 마찬가지다. 여기서는 공식 문서 방식으로 맹목적으로 API 소개를 작성하는 것이 아니라 이론과 실제 비즈니스 요구 사항을 결합하는 것에 관한 것입니다. 그렇다면 요약이 아닌 연구 노트가 될 것입니다.

반응형 폼을 주로 도입하는 이유는 무엇인가요? 반응형 양식은 기본 양식 개체 모델에 대한 직접적이고 명시적인 액세스를 제공하기 때문입니다. 템플릿 기반 양식보다 더 강력합니다. 즉, 확장성, 재사용성, 테스트 가능성이 더 높습니다. 사실 더 복잡한 형태에 적합합니다. 사실 가장 중요한 것은 다른 일을 할 줄 모른다는 것입니다. [관련 튜토리얼 추천: "angular 튜토리얼"]

1. 반응형 폼의 기본 개념

1.FormControl, FormArray, FormGroup

1.FormControl: 단일 값을 추적하는 데 사용됩니다. 양식 컨트롤 및 필드 바인딩과 같은 유효성 검사 상태

//初始化一个栏位的值为测试名字,并且不可用
const Name:FormControl = new FormControl({value:'测试名字', disabled: true });
로그인 후 복사

2.FormArray: 여러 필드가 함께 사용되는, 일반적으로 사용되는 테이블 또는 양식에 포함된 테이블과 같은 양식 컨트롤 배열의 값과 상태를 추적하는 데 사용됩니다

//定义表单对象的属性为aliases的FormArray 
this.validateForm = this.fb.group({aliases: this.fb.array([]),});

//获取FormArray 
get aliases() {return this.validateForm.get('aliases') as FormArray;}

//给FormArray 添加item
this.aliases.push(
  this.fb.group({Id: 0,Name: [null],})
);
로그인 후 복사

3 .FormGroup: 단일 양식 컨트롤의 값과 유효성 검사 상태를 추적하는 데 사용됩니다. 여기에는 단일 또는 여러 FormControl 및 FormArray가 포함될 수 있습니다. 일반적으로 양식은 FormGroup 인스턴스에 해당하고 양식의 각 필드는 FormControl에 해당합니다. 물론 FormArray는 서로 중첩될 수 있습니다. 예를 들어 FormArray는 FormGroup을 중첩할 수 있으며 유연성은 다음과 같습니다.

validateForm =  new FormGroup({Name: new FormControl({value:'测试名字', disabled: true }),});
validateForm = this.fb.group({});
로그인 후 복사

4.FormBuilder: 주입 가능한 서비스 제공자입니다. 여러 양식 컨트롤 인스턴스를 수동으로 생성하는 것은 매우 지루합니다. 과거에는 양식 컨트롤을 생성할 때마다 FormGroup을 생성해야 했습니다. 그런 다음 FormControl을 생성하고 FormBuilder의 그룹 메서드를 사용하면 반복되는 코드를 줄일 수 있습니다. 직설적으로 말하면 양식을 쉽게 생성하는 데 도움이 됩니다.

validateForm!: FormGroup;
//手动创建
validateForm = new FormGroup({
    Name: new FormControl('测试名字'),
  });
  
//FormBuilder表单构建器
validateForm = this.fb.group({
  Name:[ { value:'测试名字',disabled:true}],
});
로그인 후 복사

2. Validator 양식 유효성 검사

양식 유효성 검사를 사용하여 이를 확인합니다. 사용자의 입력이 완전하고 정확합니다. 단일 유효성 검사기를 양식 컨트롤에 추가하는 방법 및 양식의 전체 상태를 표시하는 방법 일반적으로 유효성 검사기는 모든 유효성 검사가 통과되었음을 나타내기 위해 null을 반환합니다.

1.동기식 유효성 검사기: 동기식 유효성 검사기 함수는 제어 인스턴스를 수락한 다음 유효성 검사 오류 집합 또는 null를 반환합니다. 이는 FormControl

 //formControlName的值必须和ts代码中FormControl 的实例一致
 <input type="text" id="name" class="form-control" formControlName="name" required>
 
 //判断对应的FormControl 是否没通过校验 而有错误信息
 <div *ngIf="name.errors?.[&#39;required&#39;]">
    Name is required.
 </div>
로그인 후 복사
//初始化一个栏位并且加入必填校验验证器
const name:FormControl = new FormControl({&#39;测试名字&#39;, disabled: true },Validators.required,);

//获取这个FormControl
get name() { return this.heroForm.get(&#39;name&#39;); }
로그인 후 복사

2.비동기 유효성 검사기를 인스턴스화할 때 두 번째 매개 변수로 전달할 수 있습니다. : 비동기 함수는 컨트롤 인스턴스를 받아들이고 Promise 또는 Observable을 반환합니다. Angular는 모든 동기 유효성 검사기가 통과한 후에만 이를 FormControl을 인스턴스화할 때 세 번째 매개 변수로 전달할 수 있습니다.

3. validator: 예를 들어 비워둘 수 없는 일부 길이를 확인하려면 제공된 Validator 클래스를 사용하여 이를 달성할 수 있습니다

4.Custom validator: 시스템 내에서 제공되는 유효성 검사기는 기존 요구 사항을 충족할 수 없습니다. 맞춤형 검증을 수행하려면 맞춤형 검증기가 ValidationErrors 유형 또는 비어 있는

 //formControlName的值必须和ts代码中FormControl 的实例一致
 <input type="text" id="name" class="form-control" formControlName="name" required>
 
 //判断对应的FormControl 是否没通过校验 而有错误信息
 <div *ngIf="name.hasError(&#39;Invalid&#39;)">
    名字也太长了吧....
 </div>
로그인 후 복사
//初始化一个栏位并且加入必填校验验证器
const name:FormControl = new FormControl({&#39;测试名字&#39;, disabled: true },this.CustomValidators());

CustomValidators() {
 return (control: AbstractControl): ValidationErrors | null => {
    if(control.value.length!=10)
      {
        return {Invalid:true}
      }
      return null;
    };
}
로그인 후 복사

3을 반환해야 합니다. 양식 및 요소의 기본 메소드 및 속성

  • Method
MethodUse effect
setValue() setVlue를 사용하여 컨트롤 FormControl의 값 설정 , 그러나 FormGroup의 모든 속성은 할당되어야 합니다. 함께 사용하면 단일 값을 할당할 수 없으며 부하 할당을 수정하는 데 자주 사용됩니다.
patchValue()patchValue를 사용하여 FormControl의 값을 설정할 수도 있습니다. 이를 모두 설정하지 않고도 필요에 따라 지정된 FormControl을 설정할 수 있습니다. 특정 필드 값을 업데이트하는 데 자주 사용됩니다.
reset () FormControl에서 현재 컨트롤의 모든 상태를 재설정하는 데 사용됩니다. FormGroup에서 양식 개체의 콘텐츠를 재설정하는 데 사용됩니다. 예를 들어 컨트롤이 비활성화된 경우 control.reset({ value: ' Drew',disabled:true });
markAsPristine() 양식 컨트롤 값을 변경되지 않은 상태로 표시하는 방법입니다. 이 방법은 주로 양식이 재설정될 때 사용됩니다.
markAsDirty() FormControl 컨트롤 값을 변경된 것으로 표시합니다. 이때 Dirty 상태는 true
updateValueAndValidity()FormControl 컨트롤 값과 유효성 검사 상태를 다시 계산합니다. 등
setValidators() FormControl 컨트롤에 대한 유효성 검사기를 설정합니다. 둘 이상을 설정하는 경우 "setValidators([v1,v2,v3])"
배열을 사용하세요. 비활성화()FormControl 컨트롤을 사용할 수 없도록 설정합니다. FormControl이 비활성화되면 양식의 일반 값 getValue()의 해당 값이 비어 있게 됩니다. getRawValue()를 사용하여 원래 값 개체를 가져올 수 있습니다. 해당 FormControl
enable() 값을 가져와 FormControl 컨트롤 활성화
  • Property

. 현재 컨트롤의 오류 정보 가져오기

二.实例分析及应用

1. 简单的表单实现

######需求1

我们主要用到的框架版本是Angular 12 + NG-ZORRO, 所以在下面很多实现和示例代码将与他们有关,虽然可能代码不一样,但也只是在UI层面的区别稍微大一点点,但对于TS代码,只是换汤不换药,稍微注意一下就好了,其实下面实例中的需求,基本就是我在工作时需要做的的一些基本内容和遇到的问题,经过查阅资料后解决的思路和过程,甚至截图都一模一样。

实现最基本的表单新增功能并且校验员工ID为必填以及长度不能超过50,要实现的效果图如下

Angular의 반응형 양식에 대한 간략한 분석

分析

1.首先需求未提出有特殊注意点,基本都是简单的输入框赋值然后保存,只要基本的概念搞清楚实现这种最简单

2.我们用一个FormGroup和6个FormControl 完成和界面绑定即可

3.绑定验证器用于校验长度和必填

实现步骤

1.定义html 表单结构

<!-- formGroup 属性绑定表单对象 -->
<form nz-form [formGroup]="validateForm" nzLayout="vertical">
  <nz-form-label nzRequired>Employee ID
  </nz-form-label>
  
   <!-- Employee_ErrorTrip为验证不通过弹出的提示信息 -->
   <!-- formControlName绑定表单元素FormControl -->
  <nz-form-control [nzErrorTip]="Employee_ErrorTrip">
    <input nz-input formControlName="EmployeeID"  placeholder="" />
  </nz-form-control>

  <ng-template #Employee_ErrorTrip let-control>
    <ng-container *ngIf="control.hasError(&#39;required&#39;)">
      员工编号为必填项目
    </ng-container>
  </ng-template>
</form>
로그인 후 복사

2.在TypeScript代码中声明表单对象,在构造函数中注入FormBuilder,并且在ngOnInit中进行表单初始化

//定义表单对象
validateForm:FormGroup;

//构造函数注入FormBuilder
constructor(private fb: FormBuilder){}

//在声明周期钩子函数中初始化表单
ngOnInit() {
  //初始化并且绑定必填验证器和长度验证器

    this.validateForm = this.fb.group({
      EmployeeID: [&#39;&#39;, [Validators.required, Validators.maxLength(50)]],  
    })
}
로그인 후 복사

2.在表格中应用表单

需求2

需要实现表格的表单新增和提交以及个性化定制需求,要实现的效果图和需求描述如下

1.点击Add 添加一行表格 ,编辑完毕,点击Save保存数据,点击Revoke取消编辑

2.默认开始时间和结束时间禁止使用

3.当选择Contract Type为 “短期合同” Contract start date 和Contract end date可用,当选择Contract Type为 “长期合同”不可用

4.如果Contract start date 和Contract end date可用,需要验证开始结束时间合法性,例如开始事件不能超过结束时间

Angular의 반응형 양식에 대한 간략한 분석

分析

1.在表格中使用表单,虽然表单在表格中,但是他的每一列同样都是一个个FormControl

2.一共4列需要输入值,就说明有4个FormControl 然后最后一列就是2个按钮

3.我们根据上面的基础知识知道,FormControl 不能单独使用,所以需要被FormGroup包裹,此时说明一行对应一个FormGroup

4.由一行对应一个FormGroup知道,我们的表格时多行的,也就是有多个FormGroup,我们可以使用FormArray来存储,因为他代表一组表单组

5.根据需求第2点默认开始时间和结束时间禁止使用,我们知道在一开始初始化时,设置开始结束时间对应的FormControl 为disabled就行了

6.第3点需求需要涉及联动,也就是当Contract Type对应的FormControl 的值为“短期合同”时,需要将 “开始结束时间”对应的FormControl设置为可用,这个需要自定义验证器来完成

实现步骤

1.首先定义Html表单结构

<nz-table [nzData]="CONTRACTS" nzTableLayout="fixed" [nzShowQuickJumper]="true">
  <thead>
    <tr>
      <th>Contract type</th>
      <th>Contract start date</th>
      <th>Contract end date</th>
      <th>Agreement item</th>
      <th>Operation</th>
    </tr>
  </thead>

  <tbody>
    <!-- 绑定表单组属性aliases -->
    <ng-container formArrayName="aliases">
      <!-- 将表单组中当前行的索引与formGroup绑定 -->
      <tr [formGroupName]="i" *ngFor="let data of aliases.controls;index as i">
        <td>
          <nz-form-item>
            <nz-form-control nzSpan="1-24">
              <!-- AccountName绑定FormControl  -->
              <nz-select nzShowSearch nzAllowClear nzPlaceHolder="" formControlName="Type">
                <nz-option *ngFor="let option of Type" [nzValue]="option.Code" [nzLabel]="option.Value">
                </nz-option>
              </nz-select>
            </nz-form-control>
          </nz-form-item>
          <nz-form-item>
            <nz-form-control nzSpan="1-24" [nzErrorTip]="StartDate">
              <nz-date-picker id="StartDate" formControlName="StartDate" nzPlaceHolder="">
              </nz-date-picker>
              <!-- 校验提示模板用于时间验证器 -->
              <ng-template #StartDate let-control>
              	<!-- 判断时间验证器是否存在beginGtendDate属性,如果有说明没有通过验证 然后展示提示信息 -->
                <ng-container *ngIf="control.hasError(&#39;beginGtendDate&#39;)">
                  开始时间不能晚于结束时间
                </ng-container>
              </ng-template>
            </nz-form-control>
          </nz-form-item>
          <nz-form-item>
            <nz-form-control nzSpan="1-24" [nzErrorTip]="EndDate">
              <nz-date-picker style="width: 100%;" formControlName="EndDate" nzPlaceHolder="">
              </nz-date-picker>
              <ng-template #EndDate let-control>
                <ng-container *ngIf="control.hasError(&#39;beginGtendDate&#39;)">
                  开始时间不能晚于结束时间
                </ng-container>
              </ng-template>
            </nz-form-control>
          </nz-form-item>
          <nz-form-item>
            <nz-form-control nzSpan="1-24">
              <nz-select nzShowSearch nzAllowClear nzPlaceHolder="" formControlName="ContractType">
                <nz-option *ngFor="let option of ContractTypes" [nzValue]="option.Code" [nzLabel]="option.Value">
                </nz-option>
              </nz-select>
            </nz-form-control>
          </nz-form-item>
        </td>
        <td>
          <button style="color: #009688;" nz-button nzType="text">
            <i nz-icon nzType="save"></i>Save
          </button>
          <button nz-button nzType="text" nzDanger>
            <i nz-icon nzType="redo"></i>Revoke
          </button>
        </td>
      </tr>
    </ng-container>
  </tbody>
</nz-table>
로그인 후 복사

2.在TypeScript代码中声明表单对象validateForm,然后初始化一个FormArray类型的属性aliases的实例作为表格formArrayName的值

3.点击Add按钮时向表单对象validateForm的属性aliases添加一条数据

4.定义Contract Type 联动的自定义校验器 contractTypeValidation()方法

5.定义时间校验器 timeValidation()方法,如果时间不合法,将FormControl的错误状态设置属性beginGtendDate,然后在模板中根据这个属性来选择是否渲染日式信息

//定义表单对象
validateForm:FormGroup;
//构造函数注入FormBuilder
constructor(private fb: FormBuilder){}

//在声明周期钩子函数中初始化一个表单对象validateForm
ngOnInit() {
this.validateForm = this.fb.group({
      aliases: this.fb.array([]),
 	});
}
//声明aliases属性用作界面formArrayName绑定
get aliases(){
	return this.validateForm.get(&#39;aliases&#39;) as FormArray;
}

addNewRow() {
  const group = this.fb.group({
    //添加给Type初始化验证器
    Type: [null, [CommonValidators.required, this.contractTypeValidation()]],
    //初始化禁用StartDate和EndDate的FormControl 
    StartDate: [{ value: null, disabled: true }, []],
    EndDate: [{ value: null, disabled: true },[]],
    ContractType: [null, [CommonValidators.required, CommonValidators.maxLength(20)]],
  })
  this.aliases.push(group);
}

  //自定义Contract Type验证器
contractTypeValidation() {
    return (control: AbstractControl): ValidationErrors | null => {
      let contents: any[] = this.validateForm.value.aliases;
      if (control.touched && !control.pristine) {
        //获取表单组
        const formArray: any = this.validateForm.controls.aliases;
        //找到正在编辑的行的索引
        const index = contents.findIndex((x) => !x.isShowEdit);

        //获取开始结束时间FormControl 实例
        const StartDate: AbstractControl =
          formArray.controls[index].get(&#39;StartDate&#39;),
          EndDate: AbstractControl = formArray.controls[index].get(&#39;EndDate&#39;);

        if (control.value === "短期合同") {
          //给开始结束时间设置验证器用于验证时间合法性
          StartDate.setValidators([CommonValidators.required, this.timeValidation()]);
          EndDate.setValidators([this.timeValidation()]);

          //启动开始结束时间控件
          EndDate.enable();
          StartDate.enable();
        } else {
          //Contract Type不是短期合同就清除验证器
          StartDate.clearValidators();
          EndDate.clearValidators();
          //禁用开始结束时间
          EndDate.disable();
          StartDate.disable();
        }

      }
      return null;
    }
  }



  //自定义时间验证器
 timeValidation()
  {
    return (control: AbstractControl): ValidationErrors | null => {
      if (!control.pristine) {
        let contents: any[] = this.validateForm.value.aliases;
        const formArray: any = this.validateForm.controls.aliases;
        const index = contents.findIndex((x) => !x.isShowEdit);
        //获取开始结束时间FormControl实例
        const EndDate: string = formArray.controls[index].get(&#39;EndDate&#39;).value;
        const StartDate: string =formArray.controls[index].get(&#39;StartDate&#39;).value;

        if (EndDate === null || StartDate === null) return null;

        //如果时间不合法,那就设置当前控件的错误状态 beginGtendDate为true
        if (
          Date.parse(control.value) > Date.parse(EndDate) ||
          Date.parse(control.value) < Date.parse(StartDate)
        ) {
          return { beginGtendDate: true };
        }
      }
      return null;
    }
  }
로그인 후 복사

更多编程相关知识,请访问:编程入门!!

위 내용은 Angular의 반응형 양식에 대한 간략한 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
Property사용 지침
touched FormControl 컨트롤의 touched 값이 true이면 컨트롤이 Get focus되었음을 의미하고 그 반대도 마찬가지입니다
untoucheduntouched가 true이면 이는 컨트롤이 포커스를 얻지 못했음을 의미하고, 그 반대도 마찬가지입니다
pristine은 양식 요소가 순수하고 사용자가 조작하지 않았음을 의미합니다. markAsPristine 메서드를 사용하여 true로 설정할 수 있습니다
dirty 양식 요소가 사용자에 의해 조작되었음을 나타내려면 markAsDirty 메소드를 사용하여 이를 true
status로 설정하여 FormControl 컨트롤의 상태를 가져올 수 있습니다.
Errors