Maison > Article > interface Web > Une brève analyse des formulaires réactifs dans Angular
Cet article parlera du formulaire réactif dans Angular et présentera la méthode simple de mise en œuvre du formulaire à travers des exemples. J'espère qu'il sera utile à tout le monde !
En raison de la récente mise à niveau du framework de l'entreprise, la méthode originale de vérification manuelle des formulaires a été abandonnée et tous les formulaires ont été modifiés en responsive. Comme je ne l'avais jamais utilisé auparavant, au début, je pensais que j'étais le seul à le faire. Je ne l'avais pas utilisé. Après avoir compris le groupe, j'ai appris que la plupart de mes autres collègues ne le connaissaient pas très bien. Plus tard, le temps était compté, donc je n'avais pas d'autre choix que d'apprendre et de changer en le faisant, c'était donc inévitable. J'ai dû tomber sur quelques pièges, et bien sûr j'ai aussi passé du temps à étudier. Bien que pour ceux qui le connaissent, cela puisse être très simple, mais c'est quand même une sorte de raffinement pour résumer le processus d'apprentissage et le résumé. comme les méthodes pour résoudre les problèmes. Ici, il s'agit davantage de combiner la théorie avec les besoins réels de l'entreprise, plutôt que d'écrire aveuglément des introductions d'API sous la forme de documents officiels. Si tel est le cas, il s'agira de notes d'étude et non d'un résumé.
Pourquoi introduisons-nous principalement des formulaires réactifs ? Parce que les formulaires réactifs fournissent un accès direct et explicite au
Modèle Objet de Formulairesous-jacent. Ils sont plus robustes que les formulaires basés sur des modèles : ils sont plus extensibles, réutilisables et testables. Cela convient à des formes plus complexes. En fait, le plus important est que je ne sais pas faire autre chose. [Tutoriels associés recommandés : "Tutoriel angulaire"]1. Concepts de base des formulaires réactifs
1.FormControl, FormArray, FormGroup1.
FormControl : Utilisé pour suivre la valeur d'un seul contrôle de formulaire et statut de validation, comme une liaison de champ//初始化一个栏位的值为测试名字,并且不可用
const Name:FormControl = new FormControl({value:'测试名字', disabled: true });
2.
: utilisé pour suivre la valeur et l'état d'un tableau de contrôle de formulaire, comme plusieurs champs ensemble, des tables couramment utilisées ou des tables intégrées dans le formulaire//定义表单对象的属性为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 .
: Utilisé pour suivre la valeur et l'état de validation d'un seul contrôle de formulaire. Il peut contenir un ou plusieurs FormControl et FormArray. Généralement, un formulaire correspond à une instance de FormGroup, et chaque champ du formulaire correspond à FormControl. et FormArray, bien sûr, ils peuvent s'imbriquer, par exemple, FormArray peut imbriquer FormGroup, sa flexibilité est la suivante. validateForm = new FormGroup({Name: new FormControl({value:'测试名字', disabled: true }),});
validateForm = this.fb.group({});
4.
: Il s'agit d'un fournisseur de services injectables. La création manuelle de plusieurs instances de contrôle de formulaire sera très fastidieuse. Le service FormBuilder fournit des méthodes pratiques pour générer des contrôles de formulaire. Dans le passé, chaque création devait générer un FormGroup. puis Générez FormControl, et utilisez la méthode de groupe de FormBuilder pour réduire le code répété. Pour parler franchement, cela permet de générer facilement des formulairesvalidateForm!: FormGroup;
//手动创建
validateForm = new FormGroup({
Name: new FormControl('测试名字'),
});
//FormBuilder表单构建器
validateForm = this.fb.group({
Name:[ { value:'测试名字',disabled:true}],
});
2 Validator Form validation
La validation du formulaire est utilisée pour garantir que. la saisie de l'utilisateur est complète et correcte. Comment ajouter un seul validateur à un contrôle de formulaire et comment afficher l'état global du formulaire. Habituellement, le validateur renvoie null pour indiquer que toutes les validations ont réussi.
1.
Validateur synchrone: La fonction de validation synchrone accepte une instance de contrôle, puis renvoie un ensemble d'erreurs de validation ou , qui peuvent être transmises comme deuxième paramètre lors de l'instanciation du FormControl
//formControlName的值必须和ts代码中FormControl 的实例一致 <input type="text" id="name" class="form-control" formControlName="name" required> //判断对应的FormControl 是否没通过校验 而有错误信息 <div *ngIf="name.errors?.['required']"> Name is required. </div>
//初始化一个栏位并且加入必填校验验证器 const name:FormControl = new FormControl({'测试名字', disabled: true },Validators.required,); //获取这个FormControl get name() { return this.heroForm.get('name'); }
null
2.Validateur asynchrone: La fonction asynchrone accepte une instance de contrôle et renvoie une promesse ou un observable. Angular n'exécutera le validateur asynchrone qu'après le passage de tous les validateurs synchrones. Vous pouvez le transmettre comme troisième paramètre lors de l'instanciation du FormControl. validateur : Par exemple, pour vérifier certaines longueurs, qui ne peuvent pas être vides, vous pouvez utiliser la classe Validator fournie pour implémenter
4.Validateur personnalisé : Le validateur fourni dans le système ne peut pas répondre aux besoins existants. validateur pour effectuer une vérification personnalisée. Le validateur personnalisé doit renvoyer le type ValidationErrors ou vide
//formControlName的值必须和ts代码中FormControl 的实例一致 <input type="text" id="name" class="form-control" formControlName="name" required> //判断对应的FormControl 是否没通过校验 而有错误信息 <div *ngIf="name.hasError('Invalid')"> 名字也太长了吧.... </div>
//初始化一个栏位并且加入必填校验验证器 const name:FormControl = new FormControl({'测试名字', disabled: true },this.CustomValidators()); CustomValidators() { return (control: AbstractControl): ValidationErrors | null => { if(control.value.length!=10) { return {Invalid:true} } return null; }; }
3. Méthodes et attributs de base des formulaires et des éléments
.
Méthode | Utiliser l'effet |
---|---|
setValue() | Utilisez setVlue pour définir la valeur du contrôle FormControl , mais toutes les propriétés de FormGroup doivent être attribuées ensemble, lorsqu'ils sont utilisés, ne peuvent pas se voir attribuer une seule valeur et sont souvent utilisés pour modifier les affectations de charge. |
patchValue() | En utilisant patchValue, vous pouvez également définir la valeur de FormControl. Vous pouvez définir le FormControl spécifié selon vos besoins sans tout définir. Il est souvent utilisé pour mettre à jour une certaine valeur de champ |
reset () | Utilisé dans FormControl pour réinitialiser tous les états du contrôle actuel Utilisé dans FormGroup pour réinitialiser le contenu de l'objet de formulaire. Par exemple, si le contrôle est défini sur désactivé, control.reset({ valeur : 'Drew', désactivé : true }); |
markAsPristine() | consiste à marquer la valeur du contrôle du formulaire comme inchangée. Cette méthode est principalement utilisée lorsque le formulaire est réinitialisé. true |
markAsDirty() | Il s'agit de marquer la valeur du contrôle FormControl comme modifiée. À ce moment, son statut Dirty est true |
updateValueAndValidity() | Recalculez la valeur du contrôle FormControl du formulaire. et le statut de validation, etc. |
setValidators() | Définissez les validateurs pour le contrôle FormControl Si vous en définissez plusieurs, utilisez le tableau "setValidators([v1,v2,v3])" |
disable() | Définissez le contrôle FormControl pour qu'il soit indisponible. Notez que lorsque le FormControl est désactivé, la valeur correspondante de la valeur régulière du formulaire getValue() sera vide. Vous pouvez utiliser getRawValue() pour obtenir la valeur d'origine. objet pour obtenir la valeur du FormControl |
enable() | correspondant pour définir le contrôle FormControl Enable |
Property
Propriété | Instructions à utiliser |
---|---|
touched | Lorsque la valeur touchée du contrôle FormControl est vraie, cela signifie que le contrôle a été Get focus, et vice versa |
untouched | Quand intact est vrai , cela signifie que le contrôle n'a pas obtenu le focus, et vice versa |
pristine | signifie que l'élément de formulaire est pur et n'a pas été utilisé par l'utilisateur. Vous pouvez utiliser la méthode markAsPristine pour le définir sur true. |
dirty | pour indiquer que l'élément de formulaire a été exploité par l'utilisateur. Vous pouvez utiliser la méthode markAsDirty pour le définir sur true |
status | pour obtenir l'état du contrôle FormControl. |
Erreurs | Obtenir les informations d'erreur du contrôle actuel |
1. 简单的表单实现
######需求1
我们主要用到的框架版本是Angular 12 + NG-ZORRO, 所以在下面很多实现和示例代码将与他们有关,虽然可能代码不一样,但也只是在UI层面的区别稍微大一点点,但对于TS代码,只是换汤不换药,稍微注意一下就好了,其实下面实例中的需求,基本就是我在工作时需要做的的一些基本内容和遇到的问题,经过查阅资料后解决的思路和过程,甚至截图都一模一样。
实现最基本的表单新增功能并且校验员工ID为必填以及长度不能超过50,要实现的效果图如下
分析
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('required')"> 员工编号为必填项目 </ng-container> </ng-template> </form>
2.在TypeScript代码中声明表单对象,在构造函数中注入FormBuilder,并且在ngOnInit中进行表单初始化
//定义表单对象 validateForm:FormGroup; //构造函数注入FormBuilder constructor(private fb: FormBuilder){} //在声明周期钩子函数中初始化表单 ngOnInit() { //初始化并且绑定必填验证器和长度验证器 this.validateForm = this.fb.group({ EmployeeID: ['', [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可用,需要验证开始结束时间合法性,例如开始事件不能超过结束时间
分析
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('beginGtendDate')"> 开始时间不能晚于结束时间 </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('beginGtendDate')"> 开始时间不能晚于结束时间 </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('aliases') 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('StartDate'), EndDate: AbstractControl = formArray.controls[index].get('EndDate'); 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('EndDate').value; const StartDate: string =formArray.controls[index].get('StartDate').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; } }
更多编程相关知识,请访问:编程入门!!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!