csb00
csb00

Reputation: 1155

Radio Buttons not generating an action after clicking submit

I am creating a simple help page for my app. In it, you'll get some basic documentation on how to navigate and use the site. For each talking point, I am adding a simple questionnaire ("was this helpful?") where the user clicks on the radio buttons (yes or no) and an action generates based on their selection. I was able to successfully add one to the first talking point (see snippet), but when I tried adding it to others, it won't work as when I select "no" the textarea will not appear, nor will the user get a response if they select "yes" (see snippet). I gave the second one it's own ID's and it still will not generate an action. Can someone tell me what I am doing wrong?

<div>
  <form id="myForm">
    <h4> This is the first one I was able to implement.</h4>
      <div class="custom-control custom-radio">
        <input type="radio" class="custom-control-input" id="defaultGroupExample1" name="groupOfDefaultRadios" value="yes">
          <label class="custom-control-label" for="defaultGroupExample1">Yes</label>
       </div>
       <div class="custom-control custom-radio">
          <input type="radio" class="custom-control-input" id="defaultGroupExample2" name="groupOfDefaultRadios" value="no">
              <label class="custom-control-label" for="defaultGroupExample2">No</label>
        </div>
              <input class="button" type="button" name="groupOfDefaultRadios" value="Submit">
   </form>
</div>
    <div id="result" style="display:none"></div>
                            
  <div>
    <form id="myForm">
      <h4> This one does not work</h4>
        <div class="custom-control custom-radio">
          <input type="radio" class="custom-control-input" id="defaultGroupExample3" name="groupOfDefaultRadios" value="yes">
            <label class="custom-control-label" for="defaultGroupExample2">Yes</label>
        </div>
    <div class="custom-control custom-radio">
      <input type="radio" class="custom-control-input" id="defaultGroupExample4" name="groupOfDefaultRadios" value="no">
       <label class="custom-control-label" for="defaultGroupExample3">No</label>
     </div>
     <input class="button" type="button" name="groupOfDefaultRadios" value="Submit">
     </form>
    </div>
   <div id="result" style="display:none"></div>
             
             
             <script>

let button = document.querySelector("input.button");

button.addEventListener("click", question1);


function question1() {
  var selection = document.querySelector("input[name='groupOfDefaultRadios']:checked");
        var result = document.getElementById("result");
   if (selection.value == 'yes') {
            result.innerHTML = "We're glad you found this helpful.";
        result.style.display = "block";
  } else {
    var output = "";
    output += "We're sorry! Please tell us how we can better serve you.<br />";
    output += "<textarea style='width: 500px; height 200px;'></textarea><br />";
       output += "<button>Submit</button>";
        result.innerHTML = output;
        result.style.display = "block";

      }
    }
    
    </script>

Upvotes: 1

Views: 84

Answers (2)

Ivan86
Ivan86

Reputation: 5708

Your forms had the same id and you were assigning an eventListener to only the first button element that is found on the page. As opposed to .querySelector(), .querySelectorAll() finds all the elements on the page that fit the query.

Also since the input buttons are completely the same (id, class, etc.) I used a different approach to obtain the wanted radio buttons... By finding out the parent of the clicked button we can find the radio buttons within that parent.


Edit: OP asked if response and textarea can appear for each form separately.

First change is to eliminate more than one element having the same id on the page (both result divs have the same id). If really necessary for both to have the same identifier then having the same class would make sense, not id. For the purpose of this example we will add a different id to each result div and have the id correlate to the id of its form (e.g. form id is myForm1 while it's respective result div could have an id like myForm1Result).


Try it out below:

let button = document.querySelectorAll("input.button");

button.forEach(function(elem) {
  elem.addEventListener("click", question1);
});

function question1() {
  let parent = this.parentElement;
  let parentId = parent.id;
  let resultDivId = parent.id + "Result";
  let radioBtns = parent.querySelectorAll('input[type="radio"]');
  let yesIsChecked = false;
  
  // find out which one is checked
  for(let i=0; i < radioBtns.length; i++) {
    let radio = radioBtns[i];
    if(radio.value == "yes" && radio.checked) {
      yesIsChecked = true;
    }
  }
  
  let result = document.getElementById(resultDivId);
  if (yesIsChecked) {
    result.innerHTML = "We're glad you found this helpful.";
    result.style.display = "block";
  } else {
    let output = "";
    output += "We're sorry! Please tell us how we can better serve you.<br />";
    output += "<textarea style='width: 500px; height 200px;'></textarea><br />";
    output += "<button>Submit</button>";
    result.innerHTML = output;
    result.style.display = "block";
  }
}
<div>
  <form id="myForm1">
    <h4> This is the first one I was able to implement.</h4>
    <div class="custom-control custom-radio">
      <input type="radio" class="custom-control-input" id="defaultGroupExample1" name="groupOfDefaultRadios" value="yes">
      <label class="custom-control-label" for="defaultGroupExample1">Yes</label>
    </div>
    <div class="custom-control custom-radio">
      <input type="radio" class="custom-control-input" id="defaultGroupExample2" name="groupOfDefaultRadios" value="no">
      <label class="custom-control-label" for="defaultGroupExample2">No</label>
    </div>
    <input class="button" type="button" name="groupOfDefaultRadios" value="Submit">
  </form>
</div>
<div id="myForm1Result" style="display:none"></div>

<div>
  <form id="myForm2">
    <h4> This one does not work</h4>
    <div class="custom-control custom-radio">
      <input type="radio" class="custom-control-input" id="defaultGroupExample3" name="groupOfDefaultRadios" value="yes">
      <label class="custom-control-label" for="defaultGroupExample2">Yes</label>
    </div>
    <div class="custom-control custom-radio">
      <input type="radio" class="custom-control-input" id="defaultGroupExample4" name="groupOfDefaultRadios" value="no">
      <label class="custom-control-label" for="defaultGroupExample3">No</label>
    </div>
    <input class="button" type="button" name="groupOfDefaultRadios" value="Submit">
  </form>
</div>
<div id="myForm2Result" style="display:none"></div>

Upvotes: 0

J K
J K

Reputation: 104

The document.querySelector(); function only returns the first element match, hence the event listener is only attached to the first button. Try the following code:

let buttons = document.querySelectorAll("input.button");

buttons.forEach(function (button){
  button.addEventListener("click", question1);
});

Upvotes: 1

Related Questions