Created
February 20, 2023 09:55
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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