ng-dynamic-forms
ng-dynamic-forms copied to clipboard
Custom Form Models
I'm submitting a
[ ] Bug / Regression
[x] Feature Request / Proposal
I'm using
NG Dynamic Forms Version: `13.0.0`
[x] Basic UI
[ ] Bootstrap UI
[ ] Foundation UI
[ ] Ionic UI
[ ] Kendo UI
[ ] Material
[ ] NG Bootstrap
[ ] Prime NG
Description
Now you can define custom controls and then use them to replace existing ones. As described here Custom Form Controls However it is still missing a clear description about what exactly it does, and as I understand it doesn't allow to ADD a control, it allows to REPLACE one based on the type defined in the lib.
But what if needs to be added a new model form? What would be the way to do that? I came up with a solution that requires redefining fromJSON method of DynamicFormService, but is it the way, or there is a solution that I am not aware of?
So my proposal/question is:
- if there is a good solution to add a new input model w/o injecting a new service, it has to be added to the README file.
- If there is no such way, to add one :)
@knight-bubble
I admit the docs here are not perfect. In general, you're also free to plug in your own custom model.
However, there's one limitation: at the moment a custom form control model cannot be recreated from JSON.
Thus, when using a custom form control model you need to provide your form model as code rather than JSON.
- Create a class that inherits from
DynamicFormControlModel.
export const MY_DYNAMIC_FORM_CONTROL_TYPE = "MY_CUSTOM_TYPE";
export class MyDynamicFormControlModel extends DynamicFormControlModel {
@serializable() readonly type: string = MY_DYNAMIC_FORM_CONTROL_TYPE;
//...
}
- Create a class for the corresponding custom form control according to the docs:
@Component({
selector: "my-dynamic-custom-form-control",
templateUrl: "./my-dynamic-custom-form-control.component.html",
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyDynamicCustomFormControlComponent extends DynamicFormControlComponent {
@Input() group!: FormGroup;
@Input() layout?: DynamicFormLayout;
@Input() model!: MyDynamicFormControlModel;
@Output() blur: EventEmitter<any> = new EventEmitter();
@Output() change: EventEmitter<any> = new EventEmitter();
@Output() customEvent: EventEmitter<DynamicFormControlCustomEvent> = new EventEmitter();
@Output() focus: EventEmitter<any> = new EventEmitter();
@ViewChild(MyCustomFormControlComponent) myCustomFormControlComponent!: MyCustomFormControlComponent;
constructor(protected layoutService: DynamicFormLayoutService,
protected validationService: DynamicFormValidationService) {
super(layoutService, validationService);
}
}
- Map your custom model class to your custom form control via
DYNAMIC_FORM_CONTROL_MAP_FN:
providers: [
{
provide: DYNAMIC_FORM_CONTROL_MAP_FN,
useValue: (model: DynamicFormControlModel): Type<DynamicFormControl> | null => {
switch (model.type) {
case MyDynamicFormControlModel;
return MyDynamicCustomFormControlComponent;
}
}
}
]
@udos86 should it be case MY_DYNAMIC_FORM_CONTROL_TYPE instead of case MyDynamicFormControlModel? So it would match the patterns used in the lib.
Also what if there will be added something like:
{
provide: DYNAMIC_FORM_MODEL_MAP_FN,
useValue: (type: string, model: any, layout: any): DynamicFormControlModel | null => {
switch (type) {
case MY_DYNAMIC_FORM_CONTROL_TYPE:
return new MyDynamicFormControlModel(model, layout);
}
}
}
And then in the switch of fromJSON:
....
default:
{
if (this.DYNAMIC_FORM_MODEL_MAP_FN !== undefined) {
const model2 = this.DYNAMIC_FORM_MODEL_MAP_FN(model.type, model, layout)
if (model !== null) {
formModel.push(model2);
} else {
throw new Error(`custom form control model is not resolved by type "${model.type}"`);
}
} else {
throw new Error(`unknown form control model defined on JSON with id "${model.id}"`);
}
}
break;
@knight-bubble Yes, sorry my bad!
+1, I'm also interested in adding additional form field types, like for example one that allows you to take a picture/video or upload a file or a checkbox group that would work just like the radio group, but most of all I would like to add a form field type for a signature input where it's possible to draw a signature. Is there no example set up or a tutorial article as a reference for how to go about adding completely new models?