I have a button group where each button should light up when it’s "checked". It half works which is to say it doesn’t work (only one button should be active at any time).
let stanceBar = ["long", "short", "out", "none"]
.map(
(stanceElement) =>
`
<input
type="radio"
class="btn-check"
id="${stanceElement}"
autoComplete="off"
readOnly
/>
<label
class="btn btn-outline-primary btn-sm"
for="${stanceElement}"
>
${stanceElement}
</label>
`
)
.join("")
<<This is inserted into a div>>
listeners:
document.getElementById(stance).addEventListener("click", (e) => {
let target = e.target as HTMLInputElement
s.stance = target.id
setState['s](s) // Run my setter script to kick off the for loop below
})
})
part of "setter" script
for (const stance of ["long", "short", "out", "none"]) {
const element = document.getElementById(stance)
// console.log(s.stance, "=", stance, s.stance === stance)
if (s.stance === stance) {
console.log("setting", stance, "button to", s.stance === stance)
element.setAttribute("checked", "")
} else {
console.log("setting", stance, "button to", s.stance === stance)
element.removeAttribute("checked")
}
}
When I click the buttons, I do get the button I click to activate, but the other buttons that were previously active don’t deactivate. I have debugged line by line and the removeAttribute statement is apparently running. Just nothing happens. If I run the same statement from the browser console it works fine.
let stanceBar = ["long", "short", "out", "none"]
.map(
(stanceElement) =>
`
<input
type="radio"
class="btn-check"
id="${stanceElement}"
autoComplete="off"
readOnly
/>
<label
class="btn btn-outline-primary btn-sm"
for="${stanceElement}"
>
${stanceElement}
</label>
`
)
.join("")
document.getElementById('stanceBar').innerHTML = stanceBar
;
let s = {
stance: 'none'
};
["long", "short", "out", "none"].forEach((stance) => {
document.getElementById(stance).addEventListener("click", (e) => {
let target = e.target
s.stance = target.id
setter() // setState["s"](s)
})
})
function setter() {
for (const stance of ["long", "short", "out", "none"]) {
const element = document.getElementById(stance)
if (s.stance === stance) {
element.setAttribute("checked", "")
} else {
element.removeAttribute("checked")
}
}
}
<div id='stanceBar'></div>
>Solution :
Adding a name attribute when mapping the radio buttons name="stance"
it basically acts as container & everytime you change the radio element it is overwritten as it can only have one value at a time
let stanceBar = ["long", "short", "out", "none"]
.map(
(stanceElement) =>
`
<input
type="radio"
class="btn-check"
id="${stanceElement}"
autoComplete="off"
name="stance"
readOnly
/>
<label
class="btn btn-outline-primary btn-sm"
for="${stanceElement}"
>
${stanceElement}
</label>
`
)
.join("")
document.getElementById('stanceBar').innerHTML = stanceBar
;
let s = {
stance: 'none'
};
["long", "short", "out", "none"].forEach((stance) => {
document.getElementById(stance).addEventListener("click", (e) => {
let target = e.target
s.stance = target.id
setter() // setState["s"](s)
})
})
function setter() {
for (const stance of ["long", "short", "out", "none"]) {
const element = document.getElementById(stance)
if (s.stance === stance) {
element.setAttribute("checked", "")
} else {
element.removeAttribute("checked")
}
}
}
<div id='stanceBar'></div>
