1

Short version:

Hi, I'm making a snazzy contact form for someone. It works fine without ajax. With ajax, it also works fine as long as all the form fields validate on the backend. But when I have a value that doesn't validate, even though it will return all the proper html alerting the form fields the person must fill out... All the event handlers don't work anymore, whether I made the variables global, or local scope.

Here's the steps I take, and what happens:

  1. Click a button show_form_container, and show a form (works fine).
  2. Fill out the form, click another button to hide this form, and show a captcha in it's place. This show_captcha_button then does an XMLHttpRequest() to get an image (works fine). I know I could have it loaded on the page originally, but I don't want to.
  3. When the captcha value is correct from the user's input, enable and show the form's submit button (works fine).
  4. Do another XMLHttpRequest() from the form's submit button, and load it in the proper area (works fine).
  5. When all form values would be valid on the backend, there's no problem, it does what it's supposed to do.
  6. Now when a form value is invalid on the backend, I get the XMLHttpRequest() loaded with the proper error alerts for the fields required, as it should be when I check the html (remember this is hidden, but I check the source)... Now I think this is where the issue begins... Because with this xhr.responseText, I'm loading all the html into a container. And when I click my original show_form_container button, it does nothing. The proper html is all loaded, but the event handler isn't working like it should on my showForm() function after the first invalid ajax post request.

Html:

<section id="potential_customer_section">
    <div id="container" class="indigo_border_with_center">
          <h2 class="crimson">{{ not_valid }}</h2>

          <form id="form" method="POST" action="{% url 'potential_customer_app:potential_customer' %}" novalidate>

            <div id="form_hidden" class="position_off_screen">
               {% csrf_token %}
               {{ form.as_p }}
               <input id="show_captcha_button" type='button' value='Verify as human' class="submitbox webfont">
               <div id="captcha_loading_status"></div>
            </div>


            <div id="captcha_ajax_container" class="position_off_screen">
               <h3>To prove you're human, insert the answer below as <mark>UPPERCASE ROMAN NUMERALS.</mark></h3>
               <h3>Remember that...</h3>
               <ul class="nolist">
                 <li class="tnr">I = 1</li>
                 <li class="tnr">III = 3</li>
                 <li class="tnr">IV = 4</li>
                 <li class="tnr">V = 5</li>
                 <li class="tnr">IX = 9</li>
                 <li class="tnr">X = 10</li>
               </ul>

               <div id="load_captcha_pic" class="paddingtop20px">
                 <h2 id="captcha_placeholder_text">Captcha placeholder text, remove() when ready.</h2>
               </div>

               <div id="captcha_error_check_status"><mark>***lowercase letters will not work.***</mark></div>

               <input id="user_captcha_input" class="inputbox" type="text" name="user_captcha_answer">
               <input id="correct_captcha_submit" type="submit" value="i can haz cheezbrgr!" class="submitbox margintop25px" disabled="disabled">
            </div>


          </form>
    </div>
  </section>

Javascript:

  var potential_customer_section = document.getElementById('potential_customer_section');
  var container = document.getElementById('container');
  var show_form_container = document.getElementById('show_form_container');
  var show_form_button = document.getElementById('show_form_button');
  var form = document.getElementById('form');
  var form_hidden = document.getElementById('form_hidden');
  var show_captcha_button = document.getElementById('show_captcha_button');
  var captcha_loading_status = document.getElementById('captcha_loading_status');
  var captcha_ajax_container = document.getElementById('captcha_ajax_container');
  var load_captcha_pic = document.getElementById('load_captcha_pic');
  var csrf_token = document.querySelectorAll('input[name=csrfmiddlewaretoken]')[0].value;
  var user_captcha_input = document.getElementById('user_captcha_input');


  function showForm() {
    show_form_container.className = 'disp_none';
    form_hidden.className = '';
  }
  show_form_button.onclick = showForm;



function postPotentialCustomer(e) {
    e.preventDefault();
    // get all the values of the form.....
    var xhr = new XMLHttpRequest();
    xhr.open('POST', '{% url "potential_customer_app:potential_customer" %}', true);
    xhr.onload = function() {
      if (xhr.readyState == 4 && xhr.status == 200) {
        console.log(xhr.status);
        console.log(xhr.responseText.split('<section id="potential_customer_section">')[1].split('</section>')[0]);
        potential_customer_section.innerHTML = xhr.responseText.split('<section id="potential_customer_section">')[1].split('</section>')[0];
      } else {
        console.log(xhr.status);
        potential_customer_section.innerHTML = '<h2>There was an error. Please refresh the page and try again.</h2>'
      }
    }

    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhr.send(`...`);  // All values are put here
    captcha_ajax_container.innerHTML = '<h2 class="loading">Loading...</h2>';
  }
  form.onsubmit = postPotentialCustomer;

Any help is appreciated!

  • 1
    sounds like you are destroying your original elements (happens when you set the html of the container). If so your event listeners are also destroyed they do not magically get set to the newly created elements. In that case you need to either not destroy those elements or use [event delegation](https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – Patrick Evans May 18 '19 at 01:35
  • 1
    You were right, and I fixed it. I figured it was something like whatever was in memory was being overwritten, so it had a different position in the memory *(like `a=5` then `a=9`, and expecting it to be 5 still)*. If you want points: Copy/paste your answer and I'll accept it. – CyberHavenProgramming May 19 '19 at 17:05

1 Answers1

1

Answering my own question...

The issue (as I thought if you read my comment above) was that I was deleting the old event handlers, without creating new ones in their place.

So with ajax, I instead only split out the inner portions of the form that had to be changed. That way the old event handler still worked on it's inner contents when buttons were clicked.