VA Forms Library - How to use updateSchema and replaceSchema
Occasionally, there may be a need to modify a form schema from the frontend instead of directly in vets-json-schema. This can be achieved through the use of two properties in uiSchema, updateSchema
and replaceSchema
. The primary difference between the two properties is that updateSchema
merges new schema changes with the existing one, and replaceSchema
totally removes and replaces existing schema properties.
In the regular update data flow process for Forms Library forms, both updateSchema
and replaceSchema
are handled by a single function called updateSchemaFromUiSchema.
Both updateSchema
and replaceSchema
accept the following parameters:
formData
schema
uiSchema
index - optional, provided if working with array data
path - optional, can contain the path, relative to formData, to the data corresponding to the current schema object
updateSchema
Useful for changing certain aspects of an underlying schema but maintaining the rest of it.
Example: Title change based on some other form data value using updateSchema
From the Burials form config:
updateSchema: formData => {
let title;
if (isVeteran(formData)) {
title =
'Is there anyone currently buried in a VA national cemetery under your eligibility?';
} else {
title =
'Is there anyone currently buried in a VA national cemetery under your sponsor’s eligibility?';
}
return { title };
},
Example: Changing properties in a schema
From the 10182 areaOfDisagreement uiSchema (uses this helper function):
updateSchema: (formData, _schema, _uiSchema, index) => ({
type: 'string',
maxLength: calculateOtherMaxLength(
formData.areaOfDisagreement[index],
),
}),
replaceSchema
Useful for completely changing a schema. Note: a possible gotcha when using replaceSchema
is that changing the type
of a schema may cause validation to fail on form submission because vets-api uses the original schema in vets-json-schema for data validation. If schema types do not match, submission may return an error.
Example: Changing address fields if a user lives on a military base
From the profileAddress definition:
// Replacing the city text field with a select field if a user selects military base
replaceSchema: (formData, schema, uiSchema, index) => {
const formDataPath = getPath(path, index);
const { isMilitary } = get(formDataPath, formData) ?? {};
if (isMilitary) {
return {
type: 'string',
title: 'APO/FPO/DPO',
enum: constants.militaryCities.map(city => city.value),
enumNames: constants.militaryCities.map(city => city.label),
};
}
return {
type: 'string',
title: 'City',
minLength: 1,
maxLength: 100,
pattern: STREET_PATTERN,
};
},
},
},
// Replacing the state field with different options depending on whether a user
// lives on a military base, in the United States, or in a different country
replaceSchema: (formData, schema, uiSchema, index) => {
const formDataPath = getPath(path, index);
const { country, isMilitary } = get(formDataPath, formData) ?? {};
if (isMilitary) {
return {
type: 'string',
title: 'State',
enum: constants.militaryStates.map(state => state.value),
enumNames: constants.militaryStates.map(state => state.label),
};
}
if (!isMilitary && country === 'USA') {
return {
type: 'string',
title: 'State',
enum: filteredStates.map(state => state.value),
enumNames: filteredStates.map(state => state.label),
};
}
return {
type: 'string',
title: 'State/Province/Region',
};
},
Help and feedback
Get help from the Platform Support Team in Slack.
Submit a feature idea to the Platform.