我在我的应用程序中使用了响应式表单,并使用 formcontrolName 绑定(bind)到 html。但是现在我不需要在 formbuilder 中声明属性,而是需要调用一个模型并将该模型分配给 formbuilder 并在 html 中使用它。 我浏览了很多链接,但没有找到任何地方如何根据我的要求工作。
HTML:
<div class="tab-pane fade h-100 active show" id="tab-user_1" role="tabpanel" aria-labelledby="user_1"
*ngIf="userInfoForm" [formGroup]="userInfoForm">
<div class="row">
<div class="col-6">
<div class="form-group">
<label for="">Agent Code <span class="text-danger">*</span></label>
<input type="text" formControlName="agentCode" class="form-control">
</div>
</div>
</div>
TS:
this.userInfoForm = this.FB.group({
Id: 0,
agentCode: this.agentCode,
userName: [''],
firstName: [''],
middleName: '',
lastName: [''],
department: [''],
});
this.userInfoForm.controls['agentCode'].disable();
模型.ts:
export class UserFormDetails {
Id: number;
agentCode: number;
userName: string;
firstName: string;
middleName: string;
lastName: string;
department: string;
}
最佳答案
根据评论,听起来您想要一个基于模型的动态表单……没有“开箱即用”的解决方案可以做到这一点。您可以编写自己的表单模型:
interface MyFormModelField {
initial?: {
value: any,
disabled: boolean
},
controlOptions?: AbstractControlOptions
// anything you find useful really?
}
export type MyFormModel<T> = Record<keyof T, MyFormModelField>
然后像这样实现它:
const USER_FORM_MODEL: MyFormModel<UserFormDetails> = {
Id: { },
agentCode: {
initial: {
value: '',
disabled: true
},
controlOptions: {
validators: Validators.required
}
},
userName: { },
firstName: { },
middleName: { },
lastName: { },
department: { },
}
然后您可以编写一个服务来根据表单模型的实例生成表单组...
@Injectable({providedIn: 'root'})
export class MyFormBuilder {
constructor(private: fb) { }
buildForm<T>(formModel: MyFormModel<T>) {
const fg = Object.keys(formModel).reduce((grp, k) => {
const fld = formModel[k];
return Object.assign(grp, {
[k]: [fld.initial || '', fld.controlOptions]
})
}, {});
return this.fb.group(fg);
}
}
现在,无论何时您对 UserFormDetails
界面进行更改,typescript 都会要求您使用字段信息更新相应的表单模型……虽然更新不会“自动”从模型更新,您至少在表单中具有某种类型安全性。我个人会在这里停下来。
下一部分并不完美,我不喜欢它,但如果您真的希望下一步从类定义中或多或少地自动进行,您可以编写一个函数来构建一个来自类的默认表单模型,如下所示:
function buildDefaultFormModel<T>(model: new () => T) {
return Object.keys(new model()).reduce((form, k) => {
return Object.assign(form, {[k]: {}})
}, {} as MyFormModel<T>)
}
这需要两件事,1,您为其构建表单的类必须为每个字段指定一个默认值,没有默认值的字段将不包括在内。 (这引入了对具有默认值的字段的隐藏依赖,这就是为什么我不喜欢这种方法,但是,如果您编写的类具有没有默认值或构造函数分配的属性,您可以配置 ts 对您大喊大叫):
class UserFormDetails {
Id: number = 0;
agentCode: number = 0;
userName: string = '';
firstName: string = '';
middleName: string = '';
lastName: string = '';
department: string = '';
}
2、对象的构造函数必须不带参数。但是如果你在这种情况下试图滥用它,TS 会冲你大喊大叫。
函数可以这样使用:
const USER_FORM_MODEL: MyFormModel<UserFormDetails> = {
...buildDefaultFormModel(UserFormDetails),
...{
agentCode: {
initial: {
value: '',
disabled: true
},
controlOptions: {
validators: Validators.required
}
},
}
}
这样您就可以使用默认字段,还可以为特定字段提供覆盖。
最后,您还可以利用此表单模型来构建模板,但这是一项更大的任务。
这是一个 Blitz ,所有这些都已实现(我继续清理 Controller 代码):https://stackblitz.com/edit/github-ck3u8u-qtnasc?file=src%2Fapp%2Fuser-table%2Fuser-table.validators.ts
关于angular - 如何使用 Angular 8 中的 react 形式将模型绑定(bind)到形成构建器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61657941/