@@ -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