Skip to content

Expand inputsDeferToFieldsets functionality #5

Description

@querkmachine

inputsDeferToFieldsets allows the developer to define specific inputs which should ignore the default error message placement immediately prior to the input, instead deferring the error placement to the parent fieldset (and placing the error message after the legend). This is specified by passing an array of input IDs when initialising VV.

inputsDeferToFieldsets additionally labels the message in the error summary with the legend, rather than the input's individual label.

The problem

  • A developer doesn't necessarily know what IDs are needed—such as if these IDs are generated by a CMS.
  • Having to configure by input ID doesn't practically support components that can be used multiple times on the same page.
  • A developer doesn't necessarily want the error message's placement to be moved all the way up to the fieldset. They may just want it to not be immediately prior to the input (e.g. if select element styling adds a new wrapping element and the developer wants it to appear outside of that wrapping element).

Potential resolutions

Provide more ways to specify inputs

It would seem pertinent to copy the CSS-style selector syntax used by querySelector, querySelectorAll, et al. rather than limiting a developer to only using IDs.

Provide more ways to specify placement

Inline error placement is currently limited to either being immediately before the input element with the error (the default) or to be immediately after the legend element of the parent fieldset (if inputsDeferToFieldsets specifies it). This, in my opinion at least, provides a sensible default and a reading order that is best optimised for users of assistive technologies. However, it creates problems when the demands of styling or other frameworks cannot accommodate error messages in these locations.

The proposed rectification is twofold: To provide a "basic" way of defining the inline error placement via a keyword; and to provide an "advanced" option to give developers granular control over placement.

The "basic" keyword method could include options such as:

  • before — Inserts the error before the input. This is the current default functionality.
  • after — Inserts the error after the input.
  • beforeParent — Inserts the error before the input's parent element.
  • afterParent — Inserts the error after the input's parent element.
  • fieldsetStart — Inserts the error at the start of the input's parent fieldset (after the legend). This is the current inputsDeferToFieldsets functionality.
  • fieldsetEnd — Inserts the error at the end of the input's parent fieldset.

To preserve the labelling change that inputsDeferToFieldsets performs, this should also be included as a flag.

Example usage:

new Validate(form, {
  overrideInlineErrorPlacement: [
    {
      selector: ".date-of-birth input",
      placement: "fieldsetStart",
      useLegendAsLabel: true
    }
  ]
});

There are some implementation pain points around the this. The current ID limitation exists because that is a "known" piece of information in the context the check is being made in. Whether a specific input matches a given query string is a totally different kettle of fish, and may require an excessive number of DOM queries to achieve (number of inputs being checked × number of overrides defined).

The "advanced" method I imagine would allow the developer to provide a function that is ran to determine placement:

Example usage:

new Validate(form, {
  overrideInlineErrorPlacement: [
    {
      selector: ".date-of-birth input",
      placement: function(inputElement, errorElement) {
        inputElement.closest(".date-of-birth").querySelector(".error").innerHTML = errorElement; 
      }
    }
  ]
});

If we are providing this sort of granular placement then it would make sense to provide a global setting for it. For example, allowing the developer to always have error messages be placed below an input unless otherwise overridden.

Example usage:

new Validate(form, {
  inlineErrorPlacement: "after"
});

It would also make sense to provide a limited some options for the error summary, although there isn't really anywhere it makes sense to display this except for at the start of the form/near the top of the page content.

Example usage:

new Validate(form, {
  errorSummaryPlacement: "start"
});

Backwards compatibility

For backwards compatibility with previous VV versions, I would propose keeping the inputsDeferToFieldsets parameter and format identical to how it currently is, instead mapping its functions to the new functionality which is provided under new parameter names (e.g. inlineErrorPlacement and overrideInlineErrorPlacement).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestquestionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions