Angular 表单模式切换
Angular form mode toggling
假设我们有一个非常基本的 angular 响应式表单,具有两种模式:编辑和显示。在显示模式下输入字段被禁用,在编辑模式下启用:
<form [formGroup]="formGroup" (ngSubmit)="submitForm()" novalidate>
<label for="fname">First name:</label><br />
<input
type="text"
id="fname"
name="fname"
formControlName="fname"
/><br />
<label for="lname">Last name:</label><br />
<input
type="text"
id="lname"
name="lname"
formControlName="lname"
/><br /><br />
<button type="submit">{{formMode == 'show' ? 'Edit' : 'Submit'}}</button>
</form>
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
formGroup: FormGroup;
formMode: 'show' | 'edit' = 'show';
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.formGroup = this.fb.group({
fname: [{ value: 'John', disabled: this.formMode == 'show' }],
lname: [{ value: 'Doe', disabled: this.formMode == 'show' }],
});
}
submitForm() {
if (this.formMode === 'edit') {
console.log(this.formGroup.value);
this.formMode = "show"
} else {
this.formMode = "edit"
}
}
然而,当 formMode 的状态从显示切换到编辑状态时,formControls 的禁用状态不会改变。
我知道我可以使用 this.formGroup.enable() 和 this.formGroup.disable(),但是如果有一个很大的表单并且只有一些字段在切换状态,那会是一团糟。
我预计这个禁用的道具是反应性的,因为 this.formMode 默认情况下是反应性的...
这是闪电战:
https://stackblitz.com/edit/angular-ivy-4zybd7?file=src/app/app.component.ts
我们可以创建自定义指令并将其应用于表单元素,然后在指令中注入 formGroup 指令以获取所有 formControl 路径,然后根据我们的条件可以禁用或启用。
formControlPath有什么用?
FormGroup 可以有多个 formControl.To 使用 this.control.directives.map((dir) => dir.path.join())
获取所有 formControl 名称作为数组
为什么要使用 Promise.resolve?
如果你console.log(this.formControlPath)
里面的 ngOnChanges 会是空的。要在 ngOnChanges 中获取所有已注册的 formControl 键,请使用 setTimeOut 或 Promise.resolve.
custom.directive.ts
import { Directive, Input, OnChanges, OnInit } from '@angular/core';
import { FormGroupDirective, NgControl } from '@angular/forms';
export type FormMode = 'show' | 'edit';
@Directive({
selector: '[appCanDisable]',
})
export class CanDisableDirective implements OnChanges {
@Input() formMode: FormMode;
@Input() disableFields: string[]; //Field you want to disable pass it from parent compinent
get formControlPath(): string[] {
return this.control.directives.map((dir) => dir.path.join());
}
constructor(private control: FormGroupDirective) {}
ngOnChanges() {
Promise.resolve().then(() => {
const state = this.formMode === 'show' ? 'disable' : 'enable';
this.formControlPath.forEach((path) => {
if (this.disableFields.find((field) => field === path)) {
this.control.form.get(path)[state]();
}
});
});
}
}
假设我们有一个非常基本的 angular 响应式表单,具有两种模式:编辑和显示。在显示模式下输入字段被禁用,在编辑模式下启用:
<form [formGroup]="formGroup" (ngSubmit)="submitForm()" novalidate>
<label for="fname">First name:</label><br />
<input
type="text"
id="fname"
name="fname"
formControlName="fname"
/><br />
<label for="lname">Last name:</label><br />
<input
type="text"
id="lname"
name="lname"
formControlName="lname"
/><br /><br />
<button type="submit">{{formMode == 'show' ? 'Edit' : 'Submit'}}</button>
</form>
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
formGroup: FormGroup;
formMode: 'show' | 'edit' = 'show';
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.formGroup = this.fb.group({
fname: [{ value: 'John', disabled: this.formMode == 'show' }],
lname: [{ value: 'Doe', disabled: this.formMode == 'show' }],
});
}
submitForm() {
if (this.formMode === 'edit') {
console.log(this.formGroup.value);
this.formMode = "show"
} else {
this.formMode = "edit"
}
}
然而,当 formMode 的状态从显示切换到编辑状态时,formControls 的禁用状态不会改变。
我知道我可以使用 this.formGroup.enable() 和 this.formGroup.disable(),但是如果有一个很大的表单并且只有一些字段在切换状态,那会是一团糟。
我预计这个禁用的道具是反应性的,因为 this.formMode 默认情况下是反应性的...
这是闪电战: https://stackblitz.com/edit/angular-ivy-4zybd7?file=src/app/app.component.ts
我们可以创建自定义指令并将其应用于表单元素,然后在指令中注入 formGroup 指令以获取所有 formControl 路径,然后根据我们的条件可以禁用或启用。
formControlPath有什么用?
FormGroup 可以有多个 formControl.To 使用 this.control.directives.map((dir) => dir.path.join())
为什么要使用 Promise.resolve?
如果你console.log(this.formControlPath)
里面的 ngOnChanges 会是空的。要在 ngOnChanges 中获取所有已注册的 formControl 键,请使用 setTimeOut 或 Promise.resolve.
custom.directive.ts
import { Directive, Input, OnChanges, OnInit } from '@angular/core';
import { FormGroupDirective, NgControl } from '@angular/forms';
export type FormMode = 'show' | 'edit';
@Directive({
selector: '[appCanDisable]',
})
export class CanDisableDirective implements OnChanges {
@Input() formMode: FormMode;
@Input() disableFields: string[]; //Field you want to disable pass it from parent compinent
get formControlPath(): string[] {
return this.control.directives.map((dir) => dir.path.join());
}
constructor(private control: FormGroupDirective) {}
ngOnChanges() {
Promise.resolve().then(() => {
const state = this.formMode === 'show' ? 'disable' : 'enable';
this.formControlPath.forEach((path) => {
if (this.disableFields.find((field) => field === path)) {
this.control.form.get(path)[state]();
}
});
});
}
}