Skip to content

Commit de844d0

Browse files
Preserve fieldset nested fields visibility
1 parent 3560c4c commit de844d0

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

src/helpers.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,46 @@ export function getPrefillValues(fields, initialValues = {}) {
213213
return initialValues;
214214
}
215215

216+
/**
217+
* Preserves the visibility of nested fields in a fieldset
218+
* @param {Object} field - field object
219+
* @param {String} parentPath - path to the parent field
220+
* @returns {Object} - object with a map of the visibility of the nested fields, e.g. { 'parent.child': true }
221+
*/
222+
function preserveNestedFieldsVisibility(field, parentPath = '') {
223+
return field.fields?.reduce?.((acc, f) => {
224+
const path = parentPath ? `${parentPath}.${f.name}` : f.name;
225+
if (!isNil(f.isVisible)) {
226+
acc[path] = f.isVisible;
227+
}
228+
229+
if (f.fields) {
230+
Object.assign(acc, preserveNestedFieldsVisibility(f, path));
231+
}
232+
return acc;
233+
}, {});
234+
}
235+
236+
/**
237+
* Restores the visibility of nested fields in a fieldset
238+
* @param {Object} field - field object
239+
* @param {Object} nestedFieldsVisibility - object with a map of the visibility of the nested fields, e.g. { 'parent.child': true }
240+
* @param {String} parentPath - path to the parent field
241+
*/
242+
function restoreNestedFieldsVisibility(field, nestedFieldsVisibility, parentPath = '') {
243+
field.fields.forEach((f) => {
244+
const path = parentPath ? `${parentPath}.${f.name}` : f.name;
245+
const visibility = get(nestedFieldsVisibility, path);
246+
if (!isNil(visibility)) {
247+
f.isVisible = visibility;
248+
}
249+
250+
if (f.fields) {
251+
restoreNestedFieldsVisibility(f, nestedFieldsVisibility, path);
252+
}
253+
});
254+
}
255+
216256
/**
217257
* Updates field properties based on the current JSON-schema node and the required fields
218258
*
@@ -243,10 +283,22 @@ function updateField(field, requiredFields, node, formValues, logic, config) {
243283
field.isVisible = true;
244284
}
245285

286+
// Store current visibility of fields within a fieldset before updating its attributes
287+
const nestedFieldsVisibility = preserveNestedFieldsVisibility(field);
288+
246289
const updateAttributes = (fieldAttrs) => {
247290
Object.entries(fieldAttrs).forEach(([key, value]) => {
248291
field[key] = value;
249292

293+
// If the field is a fieldset, restore the visibility of the fields within it.
294+
// If this is not in place, calling updateField for multiple conditionals touching
295+
// the same fieldset will unset previously calculated visibility for the nested fields.
296+
// This is because rebuildFieldset is called via a calculateConditionalProperties closure
297+
// created at the time of building the fields, and it returns a new fieldset.fields array
298+
if (key === 'fields' && !isNil(nestedFieldsVisibility)) {
299+
restoreNestedFieldsVisibility(field, nestedFieldsVisibility);
300+
}
301+
250302
if (key === 'schema' && typeof value === 'function') {
251303
// key "schema" refers to YupSchema that needs to be processed for validations.
252304
field[key] = value();

0 commit comments

Comments
 (0)