Not capturing form data from dynamically generated form

OK, so a user searches the db via a textbox and after an ajax Db lookup, it may show a list of values. If there’s no results, a form is generated. All working so far.
Then when the form is submitted, an evt listener runs, captures the evt.target.id, splits to array and uses array[0] to run a condition. That also works OK.

However, I can’t seem to grab the data of the form that was submitted.
I’ve made numerous attempts but the Obj is always empty.

I’d really appreciate any pointers/advice.

Edit:

For info:
The evt.target.id is split on ‘_’ because in other instances, the value may be ‘value1_value2_value3’
So, I am receiving the ‘id’ of the form submit button - assignPurchaserToListing. What am I getting wrong, that I’m not getting the form data?

Here’s what I have tried:

attempt #1 - no idea why it fails

document.form.addEventListener("click", evt => 
  {
      
  var newPurchasersDetailsObj = $("#new_purchasers_details").serializeArray();

  console.log('the obj newPurchasersDetailsObj is empty ');
  console.log(newPurchasersDetailsObj);

  } 

attempt #2 - failed because the form isn’t loaded until later?

  document.querySelector("#new_purchasers_details").addEventListener('click', function(event) {
  
  console.log('event target value = ');
  console.log(event.target.value);
  //if (event.target.tagName.toLowerCase() === 'li') {
  //  // do your action on your 'li' or whatever it is you're listening for
  //}
});

attempt #3

 document.addEventListener("click", evt => 
  {  
      var evtArray = evt.target.id.split('_', 6);
         if( evtArray[0] == 'assignPurchaserToListing' )
         { // this condition runs
         evt.preventDefault();
         var newPurchasersDetailsObj = $("#new_purchasers_details").serialize();
         
         // the following appears to be empty
         console.log('newPurchaserDetailsObj=');
         console.log( newPurchaserDetailsObj);
        }


  }

extra info:
The form that’s generated is as follows.



var detailsType = 'purchasers_details';
var detailsTypeHeading = "Purchaser's Details";
var formId = "new_" + detailsType; 
    
   outputPersonsDataEntryForm( detailsType, detailsTypeHeading, formId );
              
  
  function outputPersonsDataEntryForm( detailsType, detailsTypeHeading, formId )
  {
      str = "<form id='"
      str += formId
      str += "' name='new_"
      str += detailsType
      str += "'>"
      str += "<h2>"
      str += detailsTypeHeading 
      str +="</h2>"
      str += "<input type='hidden' id='"
      str += detailsType
      str += "' name='"
      str += detailsType
      str += "' value='"
      str += detailsType
      str += "' />" 
      str += "<input type='text' id='title' "
      str += "name='title' class=\"party-details-textbox form-control\" placeholder='Title' />"
      str += "<input type='text' id='addressName' name='addressName' class=\"party-details-textbox form-control\" placeholder='Property Name (if any)' />"
      str += "<input type='text' id='address1' name='address1' class=\"party-details-textbox form-control\" placeholder='Address Line 1' />"
      str += "<input type='text' id='address2' name='address2' class=\"party-details-textbox form-control\" placeholder='Address Line 2' />"
      str += "<input type='text' id='addressTown' name='addressTown' class=\"party-details-textbox form-control\" placeholder='Town/City'/>"
      str += "<input type='text' id='addressCounty' name='addressCounty' class=\"party-details-textbox form-control\" placeholder='County' />"
      str += "<input type='text' id='addressPostCode' name='addressPostCode' class=\"party-details-textbox form-control\" placeholder='Post Code' />"
      str += "<input type='text' id='contactNumber1' name='contactNumber1' class=\"party-details-textbox form-control\" placeholder='Main Phone Number' />"
      str += "<input type='text' id='contactNumber2' name='contactNumber2' class=\"party-details-textbox form-control\" placeholder='Second Phone Number (Optional)' />"
      str += "<input type='text' id='contactNumber3' name='contactNumber3' class=\"party-details-textbox form-control\" placeholder='Third Phone Number (Optional)' />"
      str += "<input type='text' id='contactEmail' name='contactEmail' class=\"party-details-textbox form-control\" placeholder='Email Address' />"
      str += "<input type='submit' id='assignPurchaserToListing' class='reList' style='float:right' value='Save' />"
      //str += "<button class='reList' style='float:right'>Save</button>"
      str += "</form>";
          console.log( 'str = ' + str);   
      
      $('#purchaser_details').html(str);
  }
      
      

You cant bind an event to something that isnt in the DOM yet.

It looks like youre loading jquery, so look at https://learn.jquery.com/events/event-delegation/
for their explanation of event delegation and how to implement it for elements that dont yet exist.

If youre not using jquery, you can work around it by sniffing for event.target

Attempt 3 looks like its trying to do that, but the form’s id is just “new_purchasers_details”, so you will never match “assignPurchaserToListing”…

1 Like

oh sorry, youre listening for the button click there rather than the form submission. My bad. The split confuses me though, because that id has no underscores in it. Whys there a \ before the $?

Thanks m_hutley. I’ve edited the OP to respond to your other point. The '' are needed because without them, the string breaks because using two classes, they need to be wrapped in double quotes. Not to use the backslash, means there’d be a conflict with the double quotes wrapping each ‘str’ line.

I’m going to be honest. I read that post 3 times, and my QA brain has thrown a Unknown Exception.

This line:

is not inside a string. a \ is not required in front of that $.

This is not inside a string either.

Ah, I thought your were referring to the double backslashes in the building of ‘str’. The line $(‘#purchaser_details’).html(str); requires the backslash for the perl interpreter. I’ll change it to try to make it easier to understand.

perl interpreter?

So okay wait… this is a javascript file, that is inside a perl script?

Yup. The JS is the same except for the escaping ‘\’ before each $.

Okay. I’m sticking this into Codepen and I come up with a couple of points:
1: You’re missing a ) at the end of Example 3. (Copy/paste error probably?)
2: outputPersonsDataEntryForm calls for an argument “listingId” but does not use it.
3: You’ve misnamed your variable. Look veeerry closely…

OK, apologies, those “error’s” were in copying (and typing) from my script to here. So, I still get the ‘assignPurchaserToListing’ submit button but not the data from the form that it is the button for. :frowning:


If I fix those three errors, the code works for me…

Thanks for your help so far. Yes; the form does output here but it’s when I submit it, there’s an issue. The Obj is empty.

That’s not what happens when i click the button on that form. I get in my console:

Note that you are serializeing the form. So you will get a string.

Always use your browser tool.

attempt #1

document.form.addEventListener

Is not going to work. See left bottom corner of the image

Perhaps you meant:

Cannot find ‘new_purchasers_details’ id anywhere in your form.

Why add click to a form???.

attempt#2
‘new_purchasers_details’ as above could not find.

attempt#3

Why add event listener to the whole document???.

You want to add event click listener to the button. See below.

<!DOCTYPE html>
<html>
	<body>
	  <form id='formId' name='new_type'>
	    <h2>typeHeading</h2>
	    <input type='hidden' id='type' name='type' value='type' />
	    <input type='text' id='title' name='title' class="party-details-textbox form-control" placeholder='Title' />
	    <input type='text' id='addressName' name='addressName' class="party-details-textbox form-control" placeholder='Property Name (if any)' />
	    <input type='text' id='address1' name='address1' class="party-details-textbox form-control" placeholder='Address Line 1' />
	    <input type='text' id='address2' name='address2' class="party-details-textbox form-control" placeholder='Address Line 2' />
	    <input type='text' id='addressTown' name='addressTown' class="party-details-textbox form-control" placeholder='Town/City' />
	    <input type='text' id='addressCounty' name='addressCounty' class="party-details-textbox form-control" placeholder='County' />
	    <input type='text' id='addressPostCode' name='addressPostCode' class="party-details-textbox form-control" placeholder='Post Code' />
	    <input type='text' id='contactNumber1' name='contactNumber1' class="party-details-textbox form-control" placeholder='Main Phone Number' />
	    <input type='text' id='contactNumber2' name='contactNumber2' class="party-details-textbox form-control" placeholder='Second Phone Number (Optional)' />
	    <input type='text' id='contactNumber3' name='contactNumber3' class="party-details-textbox form-control" placeholder='Third Phone Number (Optional)' />
	    <input type='text' id='contactEmail' name='contactEmail' class="party-details-textbox form-control" placeholder='Email Address' />
	    <input type='submit' id='assignPurchaserToListing' class='reList' style='float:right' value='Save' />
	  </form>
	  <script>
	    document.forms['formId']['assignPurchaserToListing'].addEventListener("click", evt => {
	      form = document.forms['formId']
	      console.log("Testing ....")
	      postalCode = form['contactEmail'].value
	      contactNumber1 = form['contactNumber1'].value
	      console.log(postalCode)
	      console.log(contactNumber1)
	    })
	  </script>
	</body>
</html>

Because the form doesnt exist until the javascript runs. You cant bind to an element that doesnt exist at the time. You could bind after attaching the element to the DOM, but… shrug. Learning about event delegation is good regardless, in case the next time you need it is “this element is added when the user clicks a button”

Ok. Perhaps this will give you an idea how to do it.

Notice the div, does not contain a form. When we click the ‘Create’ button a form will be created at run time and added to the DOM.

I am just adding one input and the button for submit (You are adding more input elements of course).

Clicking submit in the dynamically create form, and the console output the value.

Full code below.

<!DOCTYPE html>
<html>
<head>
    <title>Dynamic Form</title>
</head>
<body>
    <h1>Testing</h1>
    <form id="create">
        <input type="submit" id="createForm" class="reList" style="float: right" value="Create" />
    </form>
    <br><br>
    <div id="runTime"></div>
    <script defer>
        document.getElementById("createForm").addEventListener("click", evt => {
            evt.preventDefault(); // Prevent default form submission behavior
            // make ajax call, then create the form ...
            createForm();
        });

        // Create form at run time
        function createForm() {
        	// create the form ...
            let form = document.createElement("form");
            form.setAttribute('id', 'formId');
            form.setAttribute("method", "post");
            form.setAttribute("action", "submit");

            // create element firstName
            let firstName = document.createElement("input");
            firstName.setAttribute('id', 'firstName');
            firstName.setAttribute("placeholder", "First Name");

            // create button elment for submit ..
            let btnTag = document.createElement('label');
            let submitBtn = document.createElement("button");
            submitBtn.setAttribute('id', 'submit');
            btnTag.innerHTML = "Submit";
            submitBtn.appendChild(btnTag);

            // add elements to form ...
            form.appendChild(firstName);
            form.appendChild(submitBtn);

            // add the form to the div ...
            document.getElementById("runTime").appendChild(form);

            // on submit click on the new form, do your thing ...
             document.getElementById('submit').addEventListener("click", evt => {
            	evt.preventDefault(); // Prevent default form submission behavior
            	let firstName = document.getElementById('firstName')
            	console.log('First name: ' + firstName.value);
        	});
        }

      
    </script>
</body>
</html>

Good luck.

Thanks Zensei. Thanks to you both. I shall come back to this tomorrow evening with a fresher head. fyi: the form on-the-fly is done after, and in response to, an ajax call which returns zero results. So if there is data returned, the data shows and if there’s no data, the form shows, automatically.

Magic :slight_smile: I’ve finally got this to work. Thanks again.