stimulus-components / stimulus-reveal-controller

A Stimulus controller to toggle a class on one or multiple items to show or hide them.
https://www.stimulus-components.com/docs/stimulus-reveal-controller/
27 stars 5 forks source link

[feature suggestion] Handle hidden form inputs with `required` attribute #13

Closed dlegr250 closed 2 weeks ago

dlegr250 commented 11 months ago

This is just a suggestion for a useful feature, it's not a "ticket" or official request per se, just thought it would be useful to include in the library! I don't use the library itself, but I have referenced it a lot for some starting code.

A common use-case for a reveal/toggle/visibility controller like this is a form that asks additional questions based on user input, typically along the lines of yes/no questions with follow-up questions. If you just hide the parent items and submit the form, it will still try and validate any input items that have the HTML required attribute. A solution is to track the inputs that are required when the Stimulus controller connects and then add/remove the required attribute when shown/hidden.

This is an example Stimulus controller from one of my projects that handles this. It's not the same as the reveal controller, but is close enough to extract the useful bits of code. Note that I only have 1 "content" target, but it could easily be updated to handle multiple targets.

// Show or hide content based on the state of a radio button.
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = [ "show", "hide", "content" ]

  connect() {
    this.requiredFields = this.getRequiredFields()

    if (this.showTarget.checked) {
      this.show()
    } else {
      this.hide()
    }
  }

  show(_event) {
    this.contentTarget.style.display = "block"
    this.requiredFields.forEach((requiredField) => {
      requiredField.required = true
    })
  }

  hide(_event) {
    this.contentTarget.style.display = "none"
    this.requiredFields.forEach((requiredField) => {
      requiredField.required = false
    })
  }

  // Forms will still validate the required fields even if they are hidden.
  // Solution is to remove the [required] attribute from the fields when hidden.
  getRequiredFields() {
    return this.contentTarget.querySelectorAll("[required]")
  }
}
guillaumebriday commented 2 weeks ago

If it's still an issue, please reopen it in the main repo: https://github.com/stimulus-components/stimulus-components