@@ -213,6 +213,46 @@ export function getPrefillValues(fields, initialValues = {}) {
213
213
return initialValues ;
214
214
}
215
215
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
+
216
256
/**
217
257
* Updates field properties based on the current JSON-schema node and the required fields
218
258
*
@@ -243,10 +283,22 @@ function updateField(field, requiredFields, node, formValues, logic, config) {
243
283
field . isVisible = true ;
244
284
}
245
285
286
+ // Store current visibility of fields within a fieldset before updating its attributes
287
+ const nestedFieldsVisibility = preserveNestedFieldsVisibility ( field ) ;
288
+
246
289
const updateAttributes = ( fieldAttrs ) => {
247
290
Object . entries ( fieldAttrs ) . forEach ( ( [ key , value ] ) => {
248
291
field [ key ] = value ;
249
292
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
+
250
302
if ( key === 'schema' && typeof value === 'function' ) {
251
303
// key "schema" refers to YupSchema that needs to be processed for validations.
252
304
field [ key ] = value ( ) ;
0 commit comments