Implement form_alter-esque functionality

Created on 20 March 2024, 3 months ago

Problem/Motivation

Drupal alter hooks are really great. They allow customizations to existing things, such as a form, without having to write much code beyond the specific part being customized. What if this were also possible on the JSX layer? This would make it possible to customize forms without having to create an entire new form template, just add functionality that the primary template can use if present, but otherwise go with the defaults.

Currently, every form input in the JSX Umami Demo is wrapped in the inputBehaviors higher order component. There is currently some specfic-to-one-form custom logic there

  // This is adding custom logic to the submit button in the contact message
    // feedback form. This component is not the ideal place to add logic
    // specific to a single form+input. It lives here at the moment just to
    // demonstrate it is possible.
    // This adds logic to the contact form that disables the submit button & adds
    // an instruction message until the message and subject fields are not empty.
    if (formState && formState.formId && formState.formId === 'contact-message-feedback-form' && attributes.name === 'op') {
      attributes.disabled = !(formState['message[0][value]'] && formState['subject[0][value]'])
      if (attributes.disabled) {
        passProps.renderChildren = [<p>Subject and message require values in order to submit</p>]
      }
    }

We should look into making custom logic such as this something that can be added via a separate file. Perhaps creating a formOverride configuration object, where that object can have custom functionality added based on form id / field name, and inputBehaviors invokes that functionality when there's a naming match.

For example, the "hook" like process to do the above could look like

{
 'contact-message-feedback-form' : {
    name: {
       op: (formState, attributes, passProps) = > {. 
            attributes.disabled = !(formState['message[0][value]'] && formState['subject[0][value]'])
            if (attributes.disabled) {
                passProps.renderChildren = [<p>Subject and message require values in order to submit</p>]
             }
            return [formState, attributes, passProps];
       }
    }
}

}

Then in inputBehaviors something like

if (inputBehaviors?.[formState.formId]?.[attributes.name]) {
   [formState, attributes, passProps] = inputBehaviors[formState.formId][attributes.name](formState, attributes, passProps)
}

If adding UI functionality is too elaborate at this stage, something like adding a prefix & suffix to the form elements could be a great start.

The idea in my head is arguably clearer than what I've written above, so please feel welcome to ask for clarification for what it being looked for here. The main goal is being able to alter what the templates generate without having to always create new templates.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

✨ Feature request
Status

Active

Version

1.0

Component

Umami JSX Demonstration Theme

Created by

πŸ‡ΊπŸ‡ΈUnited States bnjmnm Ann Arbor, MI

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.69.0 2024