Tzar
Tzar

Reputation: 4789

Problem when unchecking checkbox buttons in a form

In my demo form, you can run below, fieldsets are enabled sequentially on button selection. So checking a button in the first fieldset enables the second, and so on.

If all checkboxes are unchecked in the first fieldset, the form should reset and then second to the fourth fieldset should be disabled again.

However, when one of the checkboxes in the first fieldset is deselected, all other checkbox buttons in the first fieldset are also deselected, which of course is not the way it’s supposed to work.

What am I doing wrong?


document.addEventListener("DOMContentLoaded", _ => {
  const form = document.forms[0]

  // First, disable all fieldsets except the first

  function disableFieldsets() {
    const disabledFieldsets = form.querySelectorAll(
      "section:not(:first-of-type) fieldset"
    )

    for (let i = 0; i < disabledFieldsets.length; i++) {
      disabledFieldsets[i].disabled = true
    }
  }

  disableFieldsets()

  // Sequentially enable fieldsets on selection

  const sections = form.querySelectorAll("section")

  let reset = false
  
  sections.forEach(section => {
    section.addEventListener("change", function() {
      let nextFieldset = this.nextElementSibling.querySelector("fieldset")
      if (nextFieldset && !reset) {
        nextFieldset.disabled = false
      } else if (reset) {
        reset = false
      }
    })
  })

  // Reset form and disable fieldsets after all inputs in the first fieldset are deselected

  const firstFieldsetButtons = form.querySelectorAll("[name=First]")
  let isChecked = false

  firstFieldsetButtons.forEach(firstFieldsetButton => {
    firstFieldsetButton.addEventListener("click", function(e) {
      if (this.checked) {
        isChecked = true
      } else {
        form.reset()
        disableFieldsets()
      }
    })
  })
})
<main>
<form method="post" action="">    
  <section>
  <fieldset>
    <legend>First Fieldset</legend>
    <label><input type=checkbox name=First value=A>A</label>
    <label><input type=checkbox name=First value=B>B</label>
    <label><input type=checkbox name=First value=C>C</label>
  </fieldset>
  </section>
  
  <section>
  <fieldset>
    <legend>Second Fieldset</legend>
    <label><input type=radio name=Second value=1.1>1.1</label>
    <label><input type=radio name=Second value=1.2>1.2</label>
    <label><input type=radio name=Second value=1.3>1.3</label>
  </fieldset>
  </section>
  
  <section>
  <fieldset>
    <legend>Third Fieldset</legend>
    <label><input type=radio name=Third value=2.1>2.1</label>
    <label><input type=radio name=Third value=2.2>2.2</label>
    <label><input type=radio name=Third value=2.3>2.3</label>
  </fieldset>
  </section>
  
  <section>
  <fieldset>
    <legend>Fourth Fieldset</legend>
    <label><input type=radio name=Fourth value=3.1>3.1</label>
    <label><input type=radio name=Fourth value=3.2>3.2</label>
    <label><input type=radio name=Fourth value=3.3>3.3</label>
  </fieldset>
  </section>
  
  <input type=submit value=Submit>
</form>
</main>

Upvotes: 1

Views: 57

Answers (1)

A. Meshu
A. Meshu

Reputation: 4148

Make another condition like this: if(this.closest('fieldset').querySelectorAll('input:checked').length > 0) { return;}

snippet:

document.addEventListener("DOMContentLoaded", _ => {
  const form = document.forms[0]

  // First, disable all fieldsets except the first

  function disableFieldsets() {
    const disabledFieldsets = form.querySelectorAll(
      "section:not(:first-of-type) fieldset"
    )

    for (let i = 0; i < disabledFieldsets.length; i++) {
      disabledFieldsets[i].disabled = true
    }
  }

  disableFieldsets()

  // Sequentially enable fieldsets on selection

  const sections = form.querySelectorAll("section")

  let reset = false
  
  sections.forEach(section => {
    section.addEventListener("change", function() {
      let nextFieldset = this.nextElementSibling.querySelector("fieldset")
      if (nextFieldset && !reset) {
        nextFieldset.disabled = false
      } else if (reset) {
        reset = false
      }
    })
  })

  // Reset form and disable fieldsets after all inputs in the first fieldset are deselected

  const firstFieldsetButtons = form.querySelectorAll("[name=First]")
  let isChecked = false

  firstFieldsetButtons.forEach(firstFieldsetButton => {
    firstFieldsetButton.addEventListener("click", function(e) { 
      if(this.closest('fieldset').querySelectorAll('input:checked').length > 0) { return;} 
      if (this.checked) {
        isChecked = true
      }
     
      else {
        form.reset()
        disableFieldsets()
      }
    })
  })
})
<main>
<form method="post" action="">    
  <section>
  <fieldset>
    <legend>First Fieldset</legend>
    <label><input type=checkbox name=First value=A>A</label>
    <label><input type=checkbox name=First value=B>B</label>
    <label><input type=checkbox name=First value=C>C</label>
  </fieldset>
  </section>
  
  <section>
  <fieldset>
    <legend>Second Fieldset</legend>
    <label><input type=radio name=Second value=1.1>1.1</label>
    <label><input type=radio name=Second value=1.2>1.2</label>
    <label><input type=radio name=Second value=1.3>1.3</label>
  </fieldset>
  </section>
  
  <section>
  <fieldset>
    <legend>Third Fieldset</legend>
    <label><input type=radio name=Third value=2.1>2.1</label>
    <label><input type=radio name=Third value=2.2>2.2</label>
    <label><input type=radio name=Third value=2.3>2.3</label>
  </fieldset>
  </section>
  
  <section>
  <fieldset>
    <legend>Fourth Fieldset</legend>
    <label><input type=radio name=Fourth value=3.1>3.1</label>
    <label><input type=radio name=Fourth value=3.2>3.2</label>
    <label><input type=radio name=Fourth value=3.3>3.3</label>
  </fieldset>
  </section>
  
  <input type=submit value=Submit>
</form>
</main>

Upvotes: 1

Related Questions