Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checkbox Button doesn't update on Ruby on Rails #27795

Closed
mvastola opened this issue Dec 6, 2018 · 0 comments
Closed

Checkbox Button doesn't update on Ruby on Rails #27795

mvastola opened this issue Dec 6, 2018 · 0 comments

Comments

@mvastola
Copy link
Contributor

mvastola commented Dec 6, 2018

Hi,
So this just took me two hours to track down.

Background

  • I'm running into this issue on Ubuntu 18.10 both on Firefox and on Chrome, but it would appear to be browser/OS-independent.
  • When creating checkboxes using the helpers provided by Ruby on Rails (upon which many popular form helper gems like simple_form rely), RoR makes use of a paradigm that results in checkbox inputs being preceded by a hidden input tag of the same name. Example:
# Let's say that @eula.accepted is "no":
check_box("accepted", { class: 'eula_check' }, "yes", "no")
<input name="eula[accepted]" type="hidden" value="no" />
<input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />

The purpose of this is to provide a fallback value that is received in instances where the checkbox is not checked when the forum is submitted.

Normally this works quite well.

The Issue

Long story short, earlier today I went to use the BSv4 "checkbox buttons" feature, per the documentation. In what was -- in retrospect -- a moment of unchecked hubris, I imagined that this would Be Easy™ and Just Work™. (After several hours, I can now happily report I am much more humble.)

When I attempted to implement these buttons, I repeatedly ran into the problem that the checked property of the input element never changed. I created a reduced test case in JSFiddle which included this HTML:

<div class="btn-group-toggle" data-toggle="buttons">
  <label class="btn btn-info">
    <input name="checkbox" type="hidden" value="0">
    <input id="cb" name="checkbox" type="checkbox" value="1" autocomplete="off"> Click Me
  </label>
</div>

In the end, the problem appears to arise from a block of code in js/src/button.js:

const input = this._element.querySelector(Selector.INPUT)
if (input) {
if (input.type === 'radio') {
if (input.checked &&
this._element.classList.contains(ClassName.ACTIVE)) {
triggerChangeEvent = false
} else {
const activeElement = rootElement.querySelector(Selector.ACTIVE)
if (activeElement) {
$(activeElement).removeClass(ClassName.ACTIVE)
}
}
}
if (triggerChangeEvent) {
if (input.hasAttribute('disabled') ||
rootElement.hasAttribute('disabled') ||
input.classList.contains('disabled') ||
rootElement.classList.contains('disabled')) {
return
}
input.checked = !this._element.classList.contains(ClassName.ACTIVE)
$(input).trigger('change')

Particularly, at issue are these two lines of code:

const input = this._element.querySelector(Selector.INPUT)
// ... snip ...
input.checked = !this._element.classList.contains(ClassName.ACTIVE)

Essentially, the <label> tag, (to which the required classes have been added to make it appear/act like a button) expects to have it's <input type="checkbox" /> as a child. In the bootstrap source, it is identified by locating the first child element of the <label> with an <input> tag. This element then has its checked attribute flipped.

This should be a simple fix, but either the query selector needs to be more specific by either limiting itself to checkboxes and radios or excluding hidden inputs.

I will probably submit a PA shortly that should achieve this, but I wanted to create an issue as well.

Note: I'm aware it would be possible to simply specify the hidden fields outside the <label> tag, but Rails puts them together, so this would need to be done manually, and there is really no need for bootstrap to ever modify hidden fields here since radios/checkboxes used this way are already hidden for all intents and purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant