@@ -83,10 +83,41 @@ export default {
8383 },
8484
8585 handleFieldChanged (event ) {
86- this .dependentFieldValues [event .field .attribute ] = event .value ;
86+ const fullAttribute = event .field .attribute ;
87+ this .dependentFieldValues [fullAttribute] = event .value ;
88+
89+ // Also store by base attribute name (without Flexible prefix) for easier lookup
90+ const baseAttribute = this .extractBaseAttribute (fullAttribute);
91+ if (baseAttribute && baseAttribute !== fullAttribute) {
92+ this .dependentFieldValues [baseAttribute] = event .value ;
93+ }
94+
8795 this .checkDependencies ();
8896 },
8997
98+ /**
99+ * Extract the base attribute name from a potentially prefixed Flexible field attribute.
100+ * e.g., "overlay_items__0__type" -> "type"
101+ * "overlay_items[0][type]" -> "type"
102+ */
103+ extractBaseAttribute (attribute ) {
104+ if (! attribute) return null ;
105+
106+ // Pattern 1: Double underscore format (e.g., "overlay_items__0__field_name")
107+ const underscoreMatch = attribute .match (/ ^ . + __\d + __(. + )$ / );
108+ if (underscoreMatch) {
109+ return underscoreMatch[1 ];
110+ }
111+
112+ // Pattern 2: Bracket format (e.g., "overlay_items[0][field_name]")
113+ const bracketMatch = attribute .match (/ ^ . + \[ \d + \]\[ (. + )\] $ / );
114+ if (bracketMatch) {
115+ return bracketMatch[1 ];
116+ }
117+
118+ return attribute;
119+ },
120+
90121 checkDependencies () {
91122 if (! this .field .dependencies || this .field .dependencies .length === 0 ) {
92123 this .isVisible = true ;
@@ -154,10 +185,29 @@ export default {
154185 },
155186
156187 getFieldValue (fieldAttribute ) {
188+ // First check exact match in cache
157189 if (this .dependentFieldValues .hasOwnProperty (fieldAttribute)) {
158190 return this .dependentFieldValues [fieldAttribute];
159191 }
160192
193+ // Check for prefixed version in cache (for Flexible field contexts)
194+ const contextPrefix = this .getFlexibleContextPrefix ();
195+ if (contextPrefix) {
196+ const prefixedAttribute = ` ${ contextPrefix}${ fieldAttribute} ` ;
197+ if (this .dependentFieldValues .hasOwnProperty (prefixedAttribute)) {
198+ return this .dependentFieldValues [prefixedAttribute];
199+ }
200+
201+ // Try alternative formats
202+ const alternativeFormats = this .getFlexibleAttributeFormats (contextPrefix, fieldAttribute);
203+ for (const format of alternativeFormats) {
204+ if (this .dependentFieldValues .hasOwnProperty (format)) {
205+ return this .dependentFieldValues [format];
206+ }
207+ }
208+ }
209+
210+ // Fallback to finding field in DOM
161211 const field = this .findFieldByAttribute (fieldAttribute);
162212 if (field) {
163213 return field .value ;
@@ -167,8 +217,140 @@ export default {
167217 },
168218
169219 findFieldByAttribute (attribute ) {
170- const allFields = Nova .$parent ? .$refs ? .fields || [];
171- return allFields .find (f => f .field && f .field .attribute === attribute);
220+ const allFields = this .getAllFields ();
221+
222+ // First try exact match
223+ const exactMatch = allFields .find (f => f .field && f .field .attribute === attribute);
224+ if (exactMatch) {
225+ return exactMatch;
226+ }
227+
228+ // For Flexible fields: resolve attribute relative to current context
229+ const contextPrefix = this .getFlexibleContextPrefix ();
230+ if (contextPrefix) {
231+ // Try to find field with same prefix (within same Flexible group)
232+ const prefixedAttribute = ` ${ contextPrefix}${ attribute} ` ;
233+ const prefixedMatch = allFields .find (f => f .field && f .field .attribute === prefixedAttribute);
234+ if (prefixedMatch) {
235+ return prefixedMatch;
236+ }
237+
238+ // Also try alternative Flexible attribute formats
239+ const alternativeFormats = this .getFlexibleAttributeFormats (contextPrefix, attribute);
240+ for (const format of alternativeFormats) {
241+ const match = allFields .find (f => f .field && f .field .attribute === format);
242+ if (match) {
243+ return match;
244+ }
245+ }
246+ }
247+
248+ // Fallback: find any field that ends with the attribute name (for nested contexts)
249+ const suffixMatch = allFields .find (f => {
250+ if (! f .field || ! f .field .attribute ) return false ;
251+ const attr = f .field .attribute ;
252+ // Match patterns like: prefix__attribute, prefix[index][attribute]
253+ return attr .endsWith (` __${ attribute} ` ) ||
254+ attr .endsWith (` ][${ attribute} ]` ) ||
255+ attr .endsWith (` [${ attribute} ]` );
256+ });
257+
258+ return suffixMatch || null ;
259+ },
260+
261+ /**
262+ * Get all rendered fields from the Nova form.
263+ * Handles both standard Nova forms and nested Flexible field contexts.
264+ */
265+ getAllFields () {
266+ // Try Nova's global field reference first
267+ if (Nova .$parent ? .$refs ? .fields ) {
268+ return Nova .$parent .$refs .fields ;
269+ }
270+
271+ // Walk up the component tree to find fields
272+ let parent = this .$parent ;
273+ let maxDepth = 10 ;
274+
275+ while (parent && maxDepth-- > 0 ) {
276+ // Check for fields in parent's refs
277+ if (parent .$refs ? .fields && Array .isArray (parent .$refs .fields )) {
278+ return parent .$refs .fields ;
279+ }
280+ // Check for fields array directly on parent
281+ if (parent .fields && Array .isArray (parent .fields )) {
282+ return parent .fields .map (f => ({ field: f }));
283+ }
284+ parent = parent .$parent ;
285+ }
286+
287+ return [];
288+ },
289+
290+ /**
291+ * Detect the Flexible field context prefix from the container's own field attribute.
292+ * Flexible fields use prefixes like: flexible_key__index__ or flexible_key[index]
293+ */
294+ getFlexibleContextPrefix () {
295+ // Check if this container has a prefixed attribute (indicating it's inside a Flexible field)
296+ const ownAttribute = this .field ? .attribute || ' ' ;
297+
298+ // Pattern 1: Double underscore format (e.g., "overlay_items__0__field_name")
299+ const underscoreMatch = ownAttribute .match (/ ^ (. + __\d + __)/ );
300+ if (underscoreMatch) {
301+ return underscoreMatch[1 ];
302+ }
303+
304+ // Pattern 2: Bracket format (e.g., "overlay_items[0][field_name]")
305+ const bracketMatch = ownAttribute .match (/ ^ (. + \[ \d + \]\[ )/ );
306+ if (bracketMatch) {
307+ return bracketMatch[1 ];
308+ }
309+
310+ // Try to detect from parent/sibling field attributes
311+ const siblingFields = this .field ? .fields || [];
312+ for (const sibling of siblingFields) {
313+ if (sibling .attribute ) {
314+ const siblingUnderscoreMatch = sibling .attribute .match (/ ^ (. + __\d + __)/ );
315+ if (siblingUnderscoreMatch) {
316+ return siblingUnderscoreMatch[1 ];
317+ }
318+ const siblingBracketMatch = sibling .attribute .match (/ ^ (. + \[ \d + \]\[ )/ );
319+ if (siblingBracketMatch) {
320+ return siblingBracketMatch[1 ];
321+ }
322+ }
323+ }
324+
325+ return null ;
326+ },
327+
328+ /**
329+ * Generate alternative attribute formats for Flexible fields.
330+ */
331+ getFlexibleAttributeFormats (prefix , attribute ) {
332+ const formats = [];
333+
334+ // Extract the base key and index from the prefix
335+ const underscoreMatch = prefix .match (/ ^ (. + )__(\d + )__$ / );
336+ const bracketMatch = prefix .match (/ ^ (. + )\[ (\d + )\]\[ $ / );
337+
338+ if (underscoreMatch) {
339+ const [, key , index ] = underscoreMatch;
340+ // Generate bracket format alternative
341+ formats .push (` ${ key} [${ index} ][${ attribute} ]` );
342+ // Single underscore variant
343+ formats .push (` ${ key} _${ index} _${ attribute} ` );
344+ }
345+
346+ if (bracketMatch) {
347+ const [, key , index ] = bracketMatch;
348+ // Generate underscore format alternative
349+ formats .push (` ${ key} __${ index} __${ attribute} ` );
350+ formats .push (` ${ key} _${ index} _${ attribute} ` );
351+ }
352+
353+ return formats;
172354 },
173355
174356 isEmpty (value ) {
0 commit comments