Skip to content

Conditional logic not applied to nested repeaters (and nested groups) inside parent repeaters #54

Description

@elliottmangham

Summary

When a block uses a parent repeater, conditions work correctly on simple sub-fields (select, files, toggle, text) keyed off a sibling field in the same row (e.g. item_media_type == video).

They do not reliably apply to:

  1. A repeater nested inside the parent repeater row, even when the nested repeater has valid conditions on a sibling field in that row.
  2. A group nested inside another group (fields inside the inner group often render as an empty panel).

This makes it impractical to reuse composite custom fields (e.g. a shared custom/media field that contains image_sources and video_sources repeaters) inside repeater rows without duplicating the entire field schema by hand.

Environment: Blockstudio 7.2.1, WordPress block editor, classic Blockstudio theme (block.json + PHP templates).


Expected behavior

Inside a repeater row, when item_media_type (or media_type with idStructure) is image:

  • Only image-related fields are visible.
  • Nested image_sources repeater is visible.
  • Video fields (video_poster, video_mp4, video_sources, etc.) are hidden.

When item_media_type is video:

  • Only video-related fields are visible.
  • Nested video_sources repeater is visible.
  • Image fields are hidden.

Same as top-level behavior when custom/media is used outside a repeater (works correctly there).


Actual behavior

  • Simple fields in the row do respect conditions.
  • Nested repeater fields (image_sources, video_sources) leak through regardless of item_media_type / media_type — both can appear at once, or the wrong one shows for the selected type.
  • Dropping { "type": "custom/media" } inside a repeater row reproduces this, because the custom field expands to include inner repeaters.

Minimal reproduction

1. Parent repeater with a type selector + nested repeater (inline schema)

{
  "id": "items",
  "type": "repeater",
  "label": "Items",
  "attributes": [
    {
      "id": "item_media_type",
      "type": "select",
      "label": "Media type",
      "default": "image",
      "options": [
        { "value": "image", "label": "Image" },
        { "value": "video", "label": "Video" }
      ]
    },
    {
      "id": "item_image_default",
      "type": "files",
      "label": "Image",
      "allowedTypes": ["image"],
      "conditions": [[{ "id": "item_media_type", "operator": "==", "value": "image" }]]
    },
    {
      "id": "item_image_sources",
      "type": "repeater",
      "label": "Picture sources",
      "textButton": "Add picture source",
      "conditions": [[{ "id": "item_media_type", "operator": "==", "value": "image" }]],
      "attributes": [
        { "id": "source_image", "type": "files", "label": "Image", "allowedTypes": ["image"] }
      ]
    },
    {
      "id": "item_video_mp4",
      "type": "files",
      "label": "MP4",
      "allowedTypes": ["video/mp4"],
      "conditions": [[{ "id": "item_media_type", "operator": "==", "value": "video" }]]
    },
    {
      "id": "item_video_sources",
      "type": "repeater",
      "label": "Alternate video",
      "textButton": "Add alternate video",
      "conditions": [[{ "id": "item_media_type", "operator": "==", "value": "video" }]],
      "attributes": [
        { "id": "source_video_mp4", "type": "files", "label": "MP4", "allowedTypes": ["video/mp4"] }
      ]
    }
  ]
}

Steps:

  1. Add block with this repeater to the editor.
  2. Add a row; set Media type to Image.
  3. Observe: item_image_default (files) hides/shows correctly, but item_video_sources nested repeater often still visible (or both nested repeaters visible).
  4. Set Media type to Videoitem_image_sources nested repeater often still visible.

2. Same bug via custom field

{
  "type": "custom/media",
  "idStructure": "item_{id}"
}

inside the same items repeater — inner image_sources / video_sources from custom/media leak through for the same reason.

3. Related: nested group inside group

{
  "type": "group",
  "title": "Outer",
  "attributes": [
    {
      "type": "group",
      "title": "Inner",
      "attributes": [
        { "id": "heading", "type": "text", "label": "Heading" }
      ]
    }
  ]
}

Inner group shell renders but fields inside are empty (JSON validates; PHP can still read attributes if wired manually).


What works (control case)

Same conditions on non-repeater fields inside the row:

{ "id": "item_video_mp4", "type": "files", "conditions": [[{ "id": "item_media_type", "operator": "==", "value": "video" }]] }

These toggle correctly. Only nested repeaters (and nested groups) break down.

Top-level custom/media outside any repeater: all conditions work as documented.


Impact

Common patterns blocked or expensive:

  • Per-row media in tabs, accordions, carousels, feature lists
  • Reusing shared composite custom fields inside repeaters
  • DRY field libraries — forces ~25+ duplicated flat fields per block or a parallel field definition (media-row) without inner repeaters

Docs reference repeater conditional context:
Conditional logic — repeater context

Simple fields in repeater context behave as documented; nested repeaters do not.


Current workaround

  1. Flat fields — duplicate all sub-fields in the row with conditions on a row-level type select (works, high maintenance).
  2. Custom field variant without inner repeaters — e.g. single flat “swap” slots instead of image_sources / video_sources repeaters (what we shipped as custom/media-row).
  3. Avoid nested groups — single group level only; use idStructure for multiple instances.

Suggested fix / feature request

  • Evaluate conditions for nested repeater fields using the same repeater-row context as sibling simple fields.
  • Allow custom/* fields containing repeaters to work inside parent repeaters when sub-field conditions reference fields in the expanded custom field scope.
  • Document or fix nested group behavior (either support one level of nesting or explicitly error/warn in schema validation).

Happy to provide a minimal theme zip or screen recording if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions