1

I have a button that, when clicked, prompts the user for more info dynamically through an onclick JavaScript function:

<button type="button" id="create" onclick="addFields()">create?</button>

Once new info has been loaded into the page, I want the button to submit the form:

// .js file
function addFields(){
    var container = document.getElementById("initialinfo");
    var newInfo = document.createElement('div');
    newInfo.setAttribute("id", "createDetails");
    newInfo.innerHTML += "divs and checkboxes and radios"
    container.appendChild(newInfo);

    document.getElementById("create").removeAttribute("onclick");
    document.getElementById("create").setAttribute('type', 'submit');

}

Unfortunately, when I do this, the form doesn't submit on the next click. Instead, after the onclick event, the button (which is now of type submit) submits the form. How do I prevent this behavior?

actinidia
  • 236
  • 3
  • 17
  • 1
    Better to [avoid inline handlers entirely](https://stackoverflow.com/a/59539045), they have way too many problems to be worth using – CertainPerformance May 03 '20 at 16:21
  • Could the use of something like jQuery and its [preventDefault](https://api.jquery.com/event.preventDefault/) be useful to you? – Spoon May 03 '20 at 16:40
  • 2
    preventDefault is not from jQuery, Its part of native event API – The Fool May 03 '20 at 16:40
  • 1
    `setTimeout(()=>document.getElementById("create").setAttribute('type', 'submit'),0)` – connexo May 03 '20 at 16:58
  • ah @connexo I was thinking about timeout but then thought what if the user clicks super fast or something. Its kinda dirty. But ofc set timeout with 0 will put it to the end of the stack. Well played. – The Fool May 03 '20 at 17:02

3 Answers3

1

You can trigger the form programmatically on your second button click

<form id="myForm" action="..." >
    <button type="button" onclick="addFields(event)">continue?</button>
</form>

function addFields({target}){
    var container = document.getElementById("initialinfo");
    var newInfo = document.createElement('div');
    newInfo.setAttribute("id", "createDetails");
    newInfo.innerHTML += "divs and checkboxes and radios"
    container.appendChild(newInfo);

   // here we change the onclick event handler
   target.onclick = () => {
     const form = document.getElementById('myForm')
     form.reportValidity() && form.submit()     
   }
}
The Fool
  • 16,715
  • 5
  • 52
  • 86
  • Is using `target` instead of `document.getElementById("create")` simply a matter of elegance? – actinidia May 03 '20 at 16:47
  • yes, since you have an id, getElementById has constant lookup speed so it doesnt matter. But if you would look with something slower, using the target you know you clicked on would be more performant. Make sure you pass the event in your function in the html code. – The Fool May 03 '20 at 16:48
  • Also note I am using object deconstruction there in the function signature. – The Fool May 03 '20 at 16:49
  • If I submit this way, how do I do the built-in HTML5 validation for `` elements? – actinidia May 03 '20 at 17:44
  • You would use [reportValidity](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reportValidity). I have updated my answer to show you how to use it. – The Fool May 03 '20 at 18:04
  • For some reason, when I implement this, the form keeps reverting to default values, *then* submitting. Why might this be? – actinidia May 04 '20 at 05:13
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/213066/discussion-between-the-fool-and-tiwa-aina). – The Fool May 04 '20 at 07:21
1

Prevent Default

The Event interface's preventDefault() method tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be.

<form id="my-form">
  <input id="first-field" type="text"/>
  <input id="second-field" class="hidden" type="text"/>
  <button type="submit" id="submit">
    <span class="continue">Continue</span>
    <span class="submit hidden">Submit</span>
  </button>
</form>
.hidden {
  display: none;
}
let allFieldsShown = false;
const myForm = document.querySelector('#my-form'),
  secondField = myForm.querySelector('#second-field),
  continueText = myForm.querySelector('span.continue'),
  submitText = myForm.querySelector('span.submit');

myForm.addEventListener('submit', submitHandler);

function submitHandler(e) {
  if (!allFieldsShown) {
    e.preventDefault();
    showNode(secondField);
    hideNode(continueText);
    showNode(submitText);
    allFieldsShown = true;
  }
}

function showNode(node) {
  if (node.classList.contains('hidden')) {
    node.classList.remove('hidden');
  }
}

function hideNode(node) {
  node.classList.add('hidden');
}
Sykander
  • 26
  • 2
0

Firstly you put button type submit first and call function through onclick.
Browser will get function definition first then it will submit form

<button type="submit" id="continue" onclick="addFields()">Continue></button>
Aslam khan
  • 315
  • 1
  • 7