Skip to content

Add generic field visibility for StreamField StructBlocks#92

Merged
woodwoerk merged 3 commits into
mainfrom
feat/conditional-struct-block
Jun 8, 2026
Merged

Add generic field visibility for StreamField StructBlocks#92
woodwoerk merged 3 commits into
mainfrom
feat/conditional-struct-block

Conversation

@woodwoerk

@woodwoerk woodwoerk commented May 25, 2026

Copy link
Copy Markdown
Collaborator

Add a generic pattern for showing/ hiding fields within a StructBlock in Wagtail streamfields based on the value of a sibling ChoiceBlock field.

Purpose

When a StructBlock has fields that are only relevant for certain choices (e.g. layout-specific settings), the admin shows all fields unconditionally. This change aims to improve the user experience by only showing necessary and relevant fields.

Solution (summary by Claude)

blocks/conditional_struct_block.py — A ConditionalStructBlock base class. Subclasses declare conditional_rules at class level:

class MyBlock(ConditionalStructBlock):
    conditional_rules = [
        ConditionalFieldRule(trigger='layout', target='extra_settings', show_for=['advanced']),
    ]

Subclasses with non-empty rules are auto-registered via init_subclass. get_conditional_rules_config() serialises all registered rules as a JSON object keyed by block fingerprint — the sorted set of the block's declared field names, which uniquely identifies the block type in the DOM without requiring Wagtail internals changes.

static/kausal_common/js/conditional_struct_block.js — A single generic MutationObserver script that reads window.KAUSAL_CONDITIONAL_RULES and sets up show/hide listeners on any matching .struct-block using data-contentpath selectors. The fingerprint is computed from direct children only to avoid false matches from nested struct-blocks.

wagtail_hooks.py — An insert_editor_js hook that injects the rules config as an inline <script> followed by the JS file. Because kausal_common is in INSTALLED_APPS, the hook is discovered automatically; no registration is needed in consuming apps.

Usage
Extend ConditionalStructBlock instead of blocks.StructBlock and declare conditional_rules.


✅ Pre-Merge Checklist

Type of Change

  • Set the PR's label to match the nature of this change

Testing

  • Built Unit tests (unit tests added/updated)
  • Built E2E tests (if applicable. E2E tests added/updated)
  • Authorization is tested (permissions and access controls verified)
  • Manually tested locally in all affected projects (functionality verified)
    Manual testing instructions
    If feature requires manual testing by reviewer, you can provide instructions here.

Internationalization & Accessibility

  • New strings are translatable (all user-facing text uses i18n)
  • Accessibility standards met (WCAG compliance, screen reader support)

Dependencies

  • Dependencies are merged (if applicable. If the change depends on other PRs)

@woodwoerk woodwoerk requested a review from tituomin May 25, 2026 13:58
@woodwoerk woodwoerk added the New feature New feature (non-breaking change which adds functionality) label May 25, 2026
@woodwoerk

Copy link
Copy Markdown
Collaborator Author

@tituomin The fingerprinting approach to associate Wagtail generated blocks with client-side JS feels a bit flaky, there might be another way to handle that

@tituomin tituomin force-pushed the feat/conditional-struct-block branch from c73b0bd to 356c60a Compare June 3, 2026 12:34
@woodwoerk woodwoerk merged commit c4ca4a5 into main Jun 8, 2026
@woodwoerk woodwoerk deleted the feat/conditional-struct-block branch June 8, 2026 05:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

New feature New feature (non-breaking change which adds functionality)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants