Problem/Motivation

JSON Schema's required keyword only checks that a property exists in an object — it does not enforce that string values are non-empty. When a string field is marked as required, JSON Editor initializes it with an empty string ("") and the form allows submission without the user entering a value. The required asterisk appears on the field, but the "Value required" inline error is never displayed.

This manifests most visibly on media fields (e.g., Image URL) where selecting nothing submits an empty string that silently passes validation. The general validation popup says "See error below" but no field-specific message appears.

Additionally, the AJAX wrappers for beforeSerialize and beforeSubmit use hasOwnProperty guards and closure-captured editor references that can silently skip wrapper installation or reference stale editor instances when Layout Builder replaces DOM (e.g., editing multiple blocks in sequence, or re-opening a block after cancellation).

Steps to reproduce

  1. Add "required": ["image_url"] in a pattern's schema file to make a string field required.
  2. Enable Patternkit and the Patternkit Example module.
  3. Configure a node type with Layout Builder enabled.
  4. Create content and open the Layout Builder tab.
  5. Add a [Patternkit] Example block.
  6. Leave the required image field empty.
  7. Click "Add block" / "Save".

Expected: A "Value required" error appears on the image field and submission is blocked.

Actual: The general popup says "See error below" but no field-specific error appears. The form may submit with an empty string value.

Proposed resolution

Three changes addressing validation enforcement, error display, and submission reliability:

1. Custom validator for required string fields

  • Adds a custom validator to JSONEditor.defaults.custom_validators that checks properties listed in a schema's required array with type: "string".
  • Produces a "Value required" (error_notempty) error when the value is an empty string or whitespace-only.
  • Registration is idempotent via a patternkitRequiredStringValidator flag to prevent duplicate validators across multiple attach() cycles.

2. Media field inline validation error display

  • Overrides showValidationErrors() in DrupalMediaEditor (AbstractEditor subclass in patternkit_media_library).
  • The parent class has a no-op implementation, so media fields previously swallowed validation errors silently.
  • Filters errors by path and delegates to the theme's addInputError/removeInputError for consistent styling.

3. Form submission gates and AJAX wrapper rework

  • Non-AJAX: onSubmit() validates before allowing form submission; blocks and displays inline errors if validation fails.
  • AJAX: New validateBeforeAjaxSubmit() method intercepts Drupal's AJAX submit flow; resets ajax.ajaxing flag and re-enables the submit button on failure so users can correct errors and retry.
  • Passes the current editor value to validate() to force fresh validation, bypassing the requestAnimationFrame cache that may be stale if the user edited a field and immediately clicked submit.
  • Replaced hasOwnProperty('beforeSerialize') / hasOwnProperty('beforeSubmit') guards with explicit _patternkitBeforeSerializeWrapped / _patternkitBeforeSubmitWrapped flags to prevent double-wrapping and ensure wrappers are installed reliably.
  • Wrappers now resolve the active editor via window.patternkitEditor at call time instead of capturing from the attach() closure scope, preventing stale references when Layout Builder replaces DOM.
  • Added null-safety checks before invoking previous handlers.

Remaining tasks

  • Review and test the merge request.
  • CI validation.
  • Verify no regressions in Layout Builder workflows (AJAX and non-AJAX).

User interface changes

  • Required string fields with empty or whitespace-only values now display an inline "Value required" error message.
  • Media editor fields now display inline validation error messages (previously silently ignored).
  • Form submission (both AJAX and non-AJAX) is blocked when validation errors are present.
  • The submit button remains enabled after validation failure, allowing users to correct errors and retry.
  • Existing content impact: When editing a previously-saved block that has empty values in required string fields, users will see inline validation errors and must fill in those fields before saving. Front-end rendering of existing content is unaffected.

Introduced terminology

None.

API changes

None. Changes are limited to client-side JavaScript. Server-side validation (swaggest/php-json-schema) continues to follow JSON Schema specification strictly — the required keyword checks property presence only. Schema authors can use minLength: 1 on string properties for consistent full-stack enforcement today.

Data model changes

None.

Release notes snippet

Patternkit's JSON Editor forms now enforce non-empty values for required string fields. Previously, JSON Schema's required keyword only verified that a property existed, allowing empty strings to pass validation. Required fields now display an inline "Value required" error and block form submission until a value is provided. Media editor fields also display inline validation errors that were previously silently ignored. Additionally, the AJAX form submission wrappers have been reworked to prevent stale editor references and ensure reliable wrapper installation across Layout Builder DOM replacement cycles.

Issue fork patternkit-3574404

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

slucero created an issue. See original summary.

slucero’s picture

Status: Active » Needs review

slucero changed the visibility of the branch 3574404-enforce-non-empty-values to hidden.

minsharm’s picture

Validated the issue on both D10 and D11 (11.3.3) and results look good.

The following scenarios were executed:

  • Required string validation off-canvas (AJAX)
    • Opened a PatternKit block in the off-canvas Layout Builder configuration form.
    • Cleared a required string field and clicked Update.
    • Confirmed that a “Value required” inline error appears and the block does not save.
    • Filled the field again and confirmed the save succeeds.
  • Update Pattern
    • In the off-canvas form, clicked Update pattern to refresh the schema.
    • Confirmed the success message appears: “Pattern schema updated. Review content values below, then click Update to save changes.”
    • Verified that the editor displays the current schema fields.
    • Cleared a required string field from the refreshed schema and clicked Update.
    • Confirmed validation triggers (inline error and save blocked).
    • Filled the field again and confirmed the save succeeds.
  • Update Pattern draft does not persist without save
    • Clicked Update pattern and confirmed the schema refresh.
    • Closed the off-canvas form without clicking Update (save).
    • Reopened the block and confirmed that previous values are retained, not the draft values.
  • Media field validation
    • With patternkit_media_library enabled, cleared a required media field in the off-canvas block form and attempted to save.
    • Confirmed an inline error appears on the media widget.
  • Required string validation - native form context (full page)
    • Opened the block form in full-page view (non off-canvas).
    • Cleared a required string field and submitted the form.
    • Confirmed inline validation appears and the save is blocked.
  • Happy path (off-canvas)
    • Filled all required fields and clicked Update.
    • Confirmed the block saves successfully without errors.
  • Token validation
    • Verified that valid tokens with a provided context are replaced as expected (e.g., [node:title]).
  • Schema change behavior
    • Verified that when the schema changes (e.g., a property is no longer required), clicking Update pattern refreshes the form behavior and allows normal continuation.
  • Negative scenarios
    • Validated negative scenarios (non-string / array / object / null / missing required)
  • Invalid content handling
    • Confirmed invalid content is handled gracefully (no WSOD in this flow).
    • Verified that one invalid block does not block rendering of other valid blocks.
  • Fix validation
    • Verified that fixing invalid content allows proper pattern rendering.
slucero’s picture

Status: Needs review » Reviewed & tested by the community

  • slucero committed d8f598af on 9.1.x
    [#3574404] Enforce non-empty required string validation in JSON Editor
    
slucero’s picture

Status: Reviewed & tested by the community » Fixed

Merged for inclusion in the 9.1.3 release.
See #3542304: Patternkit 9.1.3 Release Plan.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.