@cyberthreat 如承诺的那样,这是带有ngx-sub-form 的版本。
首先,这是一个现场演示的链接:https://stackblitz.com/edit/angular-td2iew
现在让我们看看它是如何构建的:
app.component.ts
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
public licenseUpdated(license: License): void {
console.log(JSON.stringify(license, null, 2));
}
}
app.component.html
<app-license-form (licenseUpdated)="licenseUpdated($event)"></app-license-form>
这里没有什么太花哨的东西,但请注意,从这个组件中我们绝对不在乎我们如何获取许可证的数据。我们只想在有更新时收到警告。
license-form.component.ts
@Component({
selector: 'app-license-form',
templateUrl: './license-form.component.html',
styleUrls: ['./license-form.component.css']
})
export class LicenseFormComponent extends NgxRootFormComponent<License> {
@DataInput()
@Input('license')
public dataInput: License | null | undefined;
@Output('licenseUpdated') public dataOutput: EventEmitter<License> = new EventEmitter();
protected getFormControls(): Controls<License> {
return {
name: new FormControl(null, [Validators.required]),
nameAttributes: new FormControl(null, [Validators.required]),
};
}
}
license-form.component.html
<form [formGroup]="formGroup">
<div>
Name<br>
<input type="text" [formControlName]="formControlNames.name">
</div>
<div>
License attributes<br>
<app-license-attributes-form [formControlName]="formControlNames.nameAttributes"></app-license-attributes-form>
</div>
<button class="save" (click)="manualSave()">Save form</button>
(look at your console to see when the form is saved!)
</form>
<div class="values">
Form group values
<pre>{{ formGroupValues | json }}</pre>
</div>
在这里,如果您不熟悉 ngx-sub-form,我会邀请您阅读该博客文章:https://dev.to/maxime1992/building-scalable-robust-and-type-safe-forms-with-angular-3nf9 和/或项目的自述文件:https://github.com/cloudnc/ngx-sub-form
这里要注意的重要一点是,我们只关心原始值,而其他所有内容都分解为子表单组件!此外,关于表单的所有内容都是类型安全的(ts 和 html!)。
license-attributes-form.component.ts
interface LicenseAttributesForm {
attributes: NameAttribute[];
}
@Component({
selector: 'app-license-attributes-form',
templateUrl: './license-attributes-form.component.html',
styleUrls: ['./license-attributes-form.component.css'],
providers: subformComponentProviders(LicenseAttributesFormComponent)
})
export class LicenseAttributesFormComponent extends NgxSubFormRemapComponent<NameAttribute[], LicenseAttributesForm> {
protected getFormControls(): Controls<LicenseAttributesForm> {
return {
attributes: new FormArray([], [Validators.required]),
};
}
protected transformToFormGroup(obj: NameAttribute[]): LicenseAttributesForm {
return {
attributes: obj ? obj : [],
};
}
protected transformFromFormGroup(formValue: LicenseAttributesForm): NameAttribute[] | null {
return formValue.attributes;
}
public addAttribute(): void {
(this.formGroupControls.attributes as FormArray).push(
this.createFormArrayControl(
'attributes',
{
index: null,
attribute: null
}
)
);
}
public removeAttribute(index: number): void {
(this.formGroupControls.attributes as FormArray).removeAt(index);
}
public createFormArrayControl(
key: any,
value: any,
): FormControl {
return new FormControl(value, [Validators.required]);
}
}
license-attributes-form.component.html
<div [formGroup]="formGroup">
<button (click)="addAttribute()">Add an attribute</button>
<div
class="attribute"
formArrayName="attributes"
*ngFor="let attribute of formGroupControls.attributes.controls; let i = index"
>
<app-license-attribute-form [formControl]="attribute"></app-license-attribute-form>
<button (click)="removeAttribute(i)">Delete</button>
</div>
</div>
最后一个
license-attribute-form.component.ts
@Component({
selector: 'app-license-attribute-form',
templateUrl: './license-attribute-form.component.html',
styleUrls: ['./license-attribute-form.component.css'],
providers: subformComponentProviders(LicenseAttributeFormComponent)
})
export class LicenseAttributeFormComponent extends NgxSubFormComponent<NameAttribute> {
protected getFormControls(): Controls<NameAttribute> {
return {
index: new FormControl(null, [Validators.required]),
attribute: new FormControl(null, [Validators.required]),
};
}
}
license-attribute-form.component.html
<form [formGroup]="formGroup">
<div>
Index<br>
<input type="number" [formControlName]="formControlNames.index">
</div>
<div>
Attribute<br>
<input type="text" [formControlName]="formControlNames.attribute">
</div>
</form>
我真的鼓励你看看 Stackblitz 并玩弄那个演示,我认为这将是更容易理解和发现的方法:)