26

I'm developing an application (a kind of social network for my university). I need to add a comment (insert a row in a specific database). To do this, I have a HTML form in my html page with various fields. At time of submit I don't use the action of form but i use a custom javascript function to elaborate some data before submitting form.

function sendMyComment() {

    var oForm = document.forms['addComment'];
    var input_video_id = document.createElement("input");
    var input_video_time = document.createElement("input");

    input_video_id.setAttribute("type", "hidden");
    input_video_id.setAttribute("name", "video_id");
    input_video_id.setAttribute("id", "video_id");
    input_video_id.setAttribute("value", document.getElementById('video_id').innerHTML);

    input_video_time.setAttribute("type", "hidden");
    input_video_time.setAttribute("name", "video_time");
    input_video_time.setAttribute("id", "video_time");
    input_video_time.setAttribute("value", document.getElementById('time').innerHTML);

    oForm.appendChild(input_video_id);
    oForm.appendChild(input_video_time);

    document.forms['addComment'].submit();
}

The last line submits the form to the correct page. It works fine. But I'd like to use ajax for submitting the form and I have no idea how to do this because I have no idea how to catch the form input values. anyone can help me?

Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
Alessio Melani
  • 333
  • 2
  • 5
  • 7
  • have you made any search ? check these links http://stackoverflow.com/questions/2530635/jquery-add-additional-parameters-on-submit-not-ajax and http://stackoverflow.com/questions/1960240/jquery-ajax-submit-form – mohsen dorparasti Nov 28 '12 at 19:24

8 Answers8

31

Nobody has actually given a pure javascript answer (as requested by OP), so here it is:

function postAsync(url2get, sendstr)    {
    var req;
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
        } else if (window.ActiveXObject) {
        req = new ActiveXObject("Microsoft.XMLHTTP");
        }
    if (req != undefined) {
        // req.overrideMimeType("application/json"); // if request result is JSON
        try {
            req.open("POST", url2get, false); // 3rd param is whether "async"
            }
        catch(err) {
            alert("couldnt complete request. Is JS enabled for that domain?\\n\\n" + err.message);
            return false;
            }
        req.send(sendstr); // param string only used for POST

        if (req.readyState == 4) { // only if req is "loaded"
            if (req.status == 200)  // only if "OK"
                { return req.responseText ; }
            else    { return "XHR error: " + req.status +" "+req.statusText; }
            }
        }
    alert("req for getAsync is undefined");
}

var var_str = "var1=" + var1  + "&var2=" + var2;
var ret = postAsync(url, var_str) ;
    // hint: encodeURIComponent()

if (ret.match(/^XHR error/)) {
    console.log(ret);
    return;
    }

In your case:

var var_str = "video_time=" + document.getElementById('video_time').value 
     + "&video_id=" + document.getElementById('video_id').value;
insaner
  • 1,395
  • 12
  • 23
  • Minor nitpick - you've called the method 'postAsync' when it actually works synchronously (the async attribute of the request is set 'false') – Psychemaster Feb 07 '17 at 09:22
  • @Psychemaster, good catch. This was modified from code I actually use, at some point I think it was specifiable as parameter for the function. I guess I just never changed that part of the name of the function. – insaner Feb 07 '17 at 15:55
  • 1
    I had to add `req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");` for this to work properly. – sevko Apr 29 '17 at 17:57
  • @sevko, yes, it depends a lot on the data you are getting back. You might have to specify "application/json" if you are receiving JSON formatted text for example. – insaner Oct 23 '17 at 05:36
29

What about

$.ajax({
  type: 'POST',
  url: $("form").attr("action"),
  data: $("form").serialize(), 
  //or your custom data either as object {foo: "bar", ...} or foo=bar&...
  success: function(response) { ... },
});
David Müller
  • 5,093
  • 2
  • 23
  • 33
  • 1
    Why we need to serialize it? – Павел Кушнеревич Oct 10 '18 at 20:07
  • You would probably need to serialize in this case so that values can keep their types when communicating with the backend code (though I believe they're very general types). This is probably very helpful if you're using JS on the backend (I normally use Python or something else but have found that this can help). – Harlin Nov 27 '19 at 00:07
10

You can add an onclick function to your submit button, but you won't be able to submit your function by pressing enter. For my part, I use this:

<form action="" method="post" onsubmit="your_ajax_function(); return false;">
    Your Name <br/>
    <input type="text" name="name" id="name" />
    <br/>
    <input type="submit" id="submit" value="Submit" />
</form>

Hope it helps.

pmrotule
  • 6,841
  • 3
  • 41
  • 49
9

You can catch form input values using FormData and send them by fetch

fetch(form.action,{method:'post', body: new FormData(form)});

function send(e,form) {
  fetch(form.action,{method:'post', body: new FormData(form)});

  console.log('We send post asynchronously (AJAX)');
  e.preventDefault();
}
<form method="POST" action="myapi/send" onsubmit="send(event,this)">
    <input hidden name="crsfToken" value="a1e24s1">
    <input name="email" value="a@b.com">
    <input name="phone" value="123-456-789">
    <input type="submit">    
</form>

Look on chrome console>network before 'submit'
Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
7

Here is a universal solution that iterates through every field in form and creates the request string automatically. It is using new fetch API. Automatically reads form attributes: method and action and grabs all fields inside the form. Support single-dimension array fields, like emails[]. Could serve as universal solution to manage easily many (perhaps dynamic) forms with single source of truth - html.

document.querySelector('.ajax-form').addEventListener('submit', function(e) {
    e.preventDefault();
    let formData = new FormData(this);
    let parsedData = {};
    for(let name of formData) {
      if (typeof(parsedData[name[0]]) == "undefined") {
        let tempdata = formData.getAll(name[0]);
        if (tempdata.length > 1) {
          parsedData[name[0]] = tempdata;
        } else {
          parsedData[name[0]] = tempdata[0];
        }
      }
    }

    let options = {};
    switch (this.method.toLowerCase()) {
      case 'post':
        options.body = JSON.stringify(parsedData);
      case 'get':
        options.method = this.method;
        options.headers = {'Content-Type': 'application/json'};
      break;
    }

    fetch(this.action, options).then(r => r.json()).then(data => {
      console.log(data);
    });
});

<form method="POST" action="some/url">
    <input name="emails[]">
    <input name="emails[]">
    <input name="emails[]">
    <input name="name">
    <input name="phone">
</form>
Maciej Kwas
  • 5,417
  • 2
  • 24
  • 43
4

It's much easier to just use jQuery, since this is just a task for university and you do not need to save code.

So, your code will look like:

function sendMyComment() {
    $('#addComment').append('<input type="hidden" name="video_id" id="video_id" value="' + $('#video_id').text() + '"/><input type="hidden" name="video_time" id="video_time" value="' + $('#time').text() +'"/>');
    $.ajax({
        type: 'POST',
        url: $('#addComment').attr('action'),
        data: $('form').serialize(), 
        success: function(response) { ... },
    });

}
chossenger
  • 589
  • 4
  • 14
Varvara Stepanova
  • 3,159
  • 4
  • 19
  • 26
2

I would suggest to use jquery for this type of requirement . Give this a try

<div id="commentList"></div>
<div id="addCommentContainer">
    <p>Add a Comment</p> <br/> <br/>
    <form id="addCommentForm" method="post" action="">
        <div>
            Your Name <br/>
            <input type="text" name="name" id="name" />


            <br/> <br/>
            Comment Body <br/>
            <textarea name="body" id="body" cols="20" rows="5"></textarea>

            <input type="submit" id="submit" value="Submit" />
        </div>
    </form>
</div>​

$(document).ready(function(){
    /* The following code is executed once the DOM is loaded */

    /* This flag will prevent multiple comment submits: */
    var working = false;
    $("#submit").click(function(){
    $.ajax({
         type: 'POST',
         url: "mysubmitpage.php",
         data: $('#addCommentForm').serialize(), 
         success: function(response) {
            alert("Submitted comment"); 
             $("#commentList").append("Name:" + $("#name").val() + "<br/>comment:" + $("#body").val());
         },
        error: function() {
             //$("#commentList").append($("#name").val() + "<br/>" + $("#body").val());
            alert("There was an error submitting comment");
        }
     });
});
});​
Pit Digger
  • 8,992
  • 23
  • 70
  • 120
  • 4
    Great function, but `var working = false` does nothing on it's own. I'm supposing you were going to use it in a conditional to prevent multiple submits. – Goose Dec 26 '15 at 03:56
1

I would like to add a new pure javascript way to do this, which in my opinion is much cleaner, by using the fetch() API. This a modern way to implements network requests. In your case, since you already have a form element we can simply use it to build our request.

const formInputs = oForm.getElementsByTagName("input");
let formData = new FormData();
for (let input of formInputs) {
    formData.append(input.name, input.value);
}

fetch(oForm.action,
    {
        method: oForm.method,
        body: formData
    })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.log(error.message))
    .finally(() => console.log("Done"));

As you can see it is very clean and much less verbose to use than XMLHttpRequest.

Alain Cruz
  • 3,588
  • 3
  • 17
  • 31