Skip to content

Instantly share code, notes, and snippets.

@goulvench
Created April 25, 2024 14:37
Show Gist options
  • Save goulvench/a5d5f44a47dc3375e275fefce3ca4122 to your computer and use it in GitHub Desktop.
Save goulvench/a5d5f44a47dc3375e275fefce3ca4122 to your computer and use it in GitHub Desktop.
A very generic Stmulus controller which can be used to show/hide, check/uncheck, enable/disable, collapse/expand, and focus fields after toggling a checkbox.
// Visit The Stimulus Handbook for more details
// https://stimulusjs.org/handbook/introduction
//
// Example HTML:
// <div data-controller="toggle-other">
// <input type="checkbox" value="nope" data-action="toggle-other#toggle" />
// <input type="checkbox" value="yeap" data-action="toggle-other#toggle" data-toggle-other-target="disable focus" />
// <input type="text" name="other" data-toggle-other-target="focus" data-toggle-other-target="enable" />
// </div>
//
// Behaviour:
// When the target is checked, the other targets are enabled/disabled, checked/unchecked, collapsed/expanded, or receive focus.
import ApplicationController from "./application_controller"
export default class extends ApplicationController {
static targets = [
"toggler",
"focus",
"disable",
"enable",
"collapse",
"uncollapse",
"check",
"uncheck",
"show",
"hide",
]
toggle(e) {
if (!this.hasTogglerTarget) {
return
}
this.toggleDisabled()
this.toggleCollapse()
this.toggleShow()
this.toggleCheck()
if (e && !this.isChecked) {
this.setFocus()
}
}
check(e) {
this.toggleCheck()
}
get is_checked() {
return this.togglerTarget.checked
}
toggleDisabled() {
const is_checked = this.is_checked
new Array(...this.disableTargets).forEach((target) =>
this.toggleDisabledTarget(target, is_checked)
)
new Array(...this.enableTargets).forEach((target) =>
this.toggleDisabledTarget(target, !is_checked)
)
}
toggleCollapse() {
const is_checked = this.is_checked
new Array(...this.collapseTargets).forEach(
function (target) {
if (is_checked) {
new bootstrap.Collapse(target, {
show: true,
})
} else {
new bootstrap.Collapse(target, {
hide: true,
})
}
}.bind(this)
)
new Array(...this.uncollapseTargets).forEach(
function (target) {
if (is_checked) {
new bootstrap.Collapse(target, {
hide: true,
})
} else {
new bootstrap.Collapse(target, {
show: true,
})
}
}.bind(this)
)
}
toggleCheck() {
const is_checked = this.is_checked
new Array(...this.checkTargets).forEach(
(target) => (target.checked = is_checked)
)
new Array(...this.uncheckTargets).forEach(
(target) => (target.checked = !is_checked)
)
}
toggleShow() {
const is_checked = this.is_checked
new Array(...this.showTargets).forEach((target) =>
target.classList.toggle("d-none", !is_checked)
)
new Array(...this.hideTargets).forEach((target) =>
target.classList.toggle("d-none", is_checked)
)
}
toggleDisabledTarget(target, is_checked) {
if (is_checked) {
target.classList.add("disabled")
target.setAttribute("disabled", "disabled")
target.setAttribute("aria-disabled", "true")
target.setAttribute("tabindex", -1)
} else {
target.classList.remove("disabled")
target.removeAttribute("disabled")
target.removeAttribute("aria-disabled")
target.removeAttribute("tabindex")
}
}
setFocus() {
if (this.hasFocusTarget) {
var focussable = this.focusTargets.filter((element) => !element.disabled)
if (focussable.length) {
focussable[0].focus()
}
} else if (this.hasDisableTarget) {
this.disableTarget.focus()
} else if (this.hasCollapseTarget) {
this.collapseTarget.focus()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment