-
Notifications
You must be signed in to change notification settings - Fork 0
Change Form Definition
On this page
- Change Form Definition
- Change the validators dynamically
- Disabling fields
- When disabling fields you might not need to change the validators
Often the form definition is constant like this:
type FormFields = {
name: string;
age: number;
};
const fd = useFormDefinition<FormFields>({
fields: {
name: {
validators: [required(), maxLength(20)]
},
age: {
validators: [required(), min(3)]
}
}
});
But sometimes we need to change the form definition based on the field values. Lets assume we also have some fields regarding the persons employment.
type FormFields = {
name: string;
age: number;
isEmployed: boolean;
companyName: string;
jobTitle: string;
};
When the person has employment (isEmployed === true
), the fields companyName
and jobTitle
are
required otherwise they are not. We can't just add the required
validator because that would make
them required when the person is not employed.
We want to change the validation rules when isEmployed
changes. We can do this with fm.onChange
which has an event handler for each field.
fm.onChange.isEmployed = value => {
const isRequired = value ?? false; // Null is considered the same as false.
fm.setValidators("companyName", isRequired ? [required()] : []);
fm.setValidators("jobTitle", isRequired ? [required()] : []);
};
When isEmployed
is not checked:
When isEmployed
is checked:
In the example above the user can fill out the companyName
and jobTitle
fields even when
isEmployed
is not checked. We want to prevent this by disabling the fields.
fm.onChange.isEmployed = value => {
const isRequired = value ?? false; // Null is considered the same as false.
fm.setValidators("companyName", isRequired ? [required()] : []);
fm.setValidators("jobTitle", isRequired ? [required()] : []);
+ fm.setIsDisabled("companyName", !isRequired);
+ fm.setIsDisabled("jobTitle", !isRequired);
};
Disabled fields does't participate in validation and is
null
infm.values
.
With this change companyName
and jobTitle
are disabled whenever isEmployed
is changed to
true
. But we also need to set the initial state because otherwise they will be enabled until
isEmployed
is changed.
const fd = useFormDefinition<FormFields>({
fields: {
name: {
validators: [required()]
},
age: {
validators: [required(), min(3)]
},
isEmployed: {
+ initialValue: false
},
companyName: {
+ initialIsDisabled: true
},
jobTitle: {
+ initialIsDisabled: true
}
}
});
We also set the initial value of isEmployed
to false. This isn't really necessary because we consider
null
to mean false
, but it makes all the relationship between the initial values a bit more clear.
You must be aware that when you set an event handler
fm.onChange.isEmployed
, you are setting a property, not adding a handler. If you set it again somewhere else in your code the first value will be lost. I recommend only setting these in one place in the code and typically right after thegetFormManager
call.
In the above example we first implemented the validators where changed when isEmployed
changed and
later we added that companyName
and jobTitle
should be disabled when the person is not
employed. As disabled fields doesn't participate in validation we can actually create the form
definition with static validators and only handle disabling the fields.
const fd = useFormDefinition<FormFields>({
fields: {
name: {
validators: [required(), maxLength(20)]
},
age: {
validators: [required(), min(3)]
},
isEmployed: {
initialValue: false
},
companyName: {
initialIsDisabled: true,
validators: [required()]
},
jobTitle: {
initialIsDisabled: true,
validators: [required()]
}
}
});
fm.onChange.isEmployed = value => {
const isEnabled = value ?? false; // Null is considered the same as false.
fm.setIsDisabled("companyName", !isEnabled);
fm.setIsDisabled("jobTitle", !isEnabled);
};