Skip to content

Instantly share code, notes, and snippets.

@koppen
Created February 20, 2023 09:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koppen/208df670913c140b09c53960f1422666 to your computer and use it in GitHub Desktop.
Save koppen/208df670913c140b09c53960f1422666 to your computer and use it in GitHub Desktop.
Stimulus controller that toggles the visibility of elements based on the current value of another element. Useful for showing different input fields based on fx a selection in a dropdown.
import { Controller } from 'stimulus'
// Sets the visibility of elements based on the checked state of a source
// element.
//
// source target is expected to emit a change event when the value changes so
// the UI can be updated.
//
// Target elements must be configured with a `data-visible-when` attribute set
// to either "on" or "off" depending on when the element should be visible. The
// element will have a CSS class added and removed from their classlist as
// applicable. Target elements are also be disabled when hidden.
//
// The actual CSS classname to use for hiding an element is configured via
// hiddenClass:
//
// <div data-controller="visibility" data-visibility-hidden-class="hidden">
export default class extends Controller {
static classes = ['hidden']
static targets = ['source', 'target']
connect () {
super.connect()
// Set initial visibility
this.setVisibility()
this.sourceTarget.addEventListener('change', this.handleChange.bind(this))
}
currentState () {
if ('checked' in this.sourceTarget) {
return this.currentValueFromCheckbox()
} else {
return this.currentValueFromInput()
}
}
currentValueFromInput () {
return this.sourceTarget.value
}
currentValueFromCheckbox () {
if (this.sourceTarget.checked) {
return 'on'
} else {
return 'off'
}
}
disconnect () {
this.sourceTarget.removeEventListener('change', this.handleChange.bind(this))
super.disconnect()
}
handleChange () {
this.setVisibility()
}
setVisibility () {
this.targetTargets.forEach(element => {
this.setVisibilityOfElement(element)
})
}
setVisibilityOfElement (element) {
if (!element.dataset.visibleWhen) return
if (element.dataset.visibleWhen === this.currentState()) {
element.classList.remove(this.hiddenClass)
element.disabled = false
} else {
element.classList.add(this.hiddenClass)
element.disabled = true
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment