I'm submitting a ... (check one with "x")
[ ] bug report => search github for a similar issue or PR before submitting
[x ] feature request
[x] support request
Expected behavior
Is possible to change runtime the type of a form field?
I would like to build a query builder I need to choice the field in the first combo box and with the type of selected field build the related control. (like here https://zebzhao.github.io/Angular-QueryBuilder/demo/ )
@aitboudad any suggestion?
not sure if it worth to support this out of the box :thinking:
ok it'll be part of an experiment extension for while, which you should import it in order to use it.
something like:
import { FormlyFieldRuntimeModule } from '@ngx-formly/core/field-runtime';
@NgModule({
imports: [
...,
FormlyFieldRuntimeModule,
],
})
export class AppModule { }
@Component({
selector: 'formly-app-example',
templateUrl: './app.component.html',
})
export class AppComponent {
fields: FormlyFieldConfig[] = [
{
key: 'custom',
type: 'field-runtime',
hideExpression: '!model.type',
expressionProperties: {
'templateOptions.type': 'model.type',
},
},
]
}
What do you think ?
@thorgod this may interest you too, since you've already asked for it, so let me know WDYT.
Thank you @aitboudad your approach is good starting point and resolve the issue.
This is my working example elaborated from your
https://stackblitz.com/edit/angular-2tdkxm-a198kc
I used ngfor to the definition of "generic" custom field-runtime
<!--Generic-->
<ng-container [ngSwitch]="field.type">
<ng-container *ngFor="let type of types">
<formly-field *ngSwitchCase="type"
[model]="field.model"
[form]="form"
[field]="field"
[options]="options">
</formly-field>
</ng-container>
</ng-container>
I'm listening in the generic field the event of selection change in order to change the type and some template property. For instance field.templateOptions.type = 'number'; or adding select options dynamically.
{
key: 'valueInput',
type: 'generic',
className: "col-md-4",
templateOptions: {
label: 'Valore',
required: true,
},
lifecycle: {
onInit: (form, field) => {
form.get('field').valueChanges.pipe(
takeUntil(this.onDestroy$),
startWith(form.get('field').value),
tap(selectedField => {
if (this.keymetadata[selectedField]) {
field.formControl.reset();
field.hideExpression = false;
field.type = this.keymetadata[selectedField].type
if (this.keymetadata[selectedField].type == 'number') {
field.templateOptions.type = 'number';
} else {
field.templateOptions.type = null;
}
}
}),
).subscribe();
}
}
}
@aitboudad any suggestion?
@aitboudad It has been a while from last time I touched that but I used it but I did it just like you suggested a while back. Snippet bellow is what I currently use in production--
<ng-container [ngSwitch]="field.type">
<formly-field *ngSwitchCase="'operator'"
[model]="field.model"
[form]="form"
[field]="field"
[options]="options">
</formly-field>
<formly-field *ngSwitchCase="'dropdown'"
[model]="field.model"
[form]="form"
[field]="field"
[options]="options">
</formly-field>
</ng-container>
export class PolymorphComponent extends FieldType implements OnInit {
constructor() {
super();
}
ngOnInit() {
this.field.wrappers = [];
...
if (delete this.field.type) {
Object.defineProperty(this.field, 'type', {
get: () => this.field.templateOptions.type,
enumerable: true,
configurable: true,
});
}
...
Object.defineProperty is what I think @enricooliva is missing.
Also had to set this to this.field.wrappers = []; to remove wrappers of wrappers of wrappers ... ;)
@enricooliva sorry I didn't quite get your question, can you elaborate please.
@aitboudad
when I change the type in the field I would like that the default options are applied.
This is the configuration of default options for the number type:
{
name: 'number',
extends: 'input',
defaultOptions: {
templateOptions: {
type: 'number',
},
},
},
@enricooliva use
formlyConfig.getMergedField(field);
in 5.0.0-beta.1 formly-field re-render when the field changes so here is my suggested way for the generic type https://stackblitz.com/edit/angular-2tdkxm-m6wa53
@aitboudad
This example stops working in 5.0.0-rc6. There is some alternative?
well I'm not yet ready to dig into this part right now (probably after V6), but I'll try at least to provide an alternative way or rollback the changes that break the above example to work
I am also changing a field's type runtime but by replacing the field entirely and relisting the fields for them to re-render, I guess that's more expensive and not the best way, but works for now, would love to change that implementation for it to just re-render the one field when it changes type.
Please @sander provide a stackbliz project.
Il ven 22 feb 2019, 15:14 Sander Struijk notifications@github.com ha
scritto:
I am also changing a field's type runtime but by replacing the field
entirely and relisting the fields for them to re-render, I guess that's
more expensive and not the best way, but works for now, would love to
change that implementation for it to just re-render the one field when it
changes type.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/ngx-formly/ngx-formly/issues/1091#issuecomment-466409602,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ALS36YKmEqinuEBu3748xs66iUVw4ARJks5vP_sogaJpZM4VwtX5
.
The dynamic field should be wrapped inside fieldGroup in order to avoid overriding the type of custom field itself which may produce some undesired side-effect.
Great, thank you so much.
Most helpful comment
see https://stackblitz.com/edit/angular-2tdkxm-yhxmoc