So I've got this HTML form:
<html>
<head><title>test</title></head>
<body>
<form action="myurl" method="POST" name="myForm">
<p><label for="first_name">First Name:</label>
<input type="text" name="first_name" id="fname"></p>
<p><label for="last_name">Last Name:</label>
<input type="text" name="last_name" id="lname"></p>
<input value="Submit" type="submit" onclick="submitform()">
</form>
</body>
</html>
Which would be the easiest way to send this form's data as a JSON object to my server when a user clicks on submit?
UPDATE:
I've gone as far as this but it doesn't seem to work:
<script type="text/javascript">
function submitform(){
alert("Sending Json");
var xhr = new XMLHttpRequest();
xhr.open(form.method, form.action, true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
var j = {
"first_name":"binchen",
"last_name":"heris",
};
xhr.send(JSON.stringify(j));
What am I doing wrong?
Get complete form data as array and json stringify it.
var formData = JSON.stringify($("#myForm").serializeArray());
You can use it later in ajax. Or if you are not using ajax; put it in hidden textarea and pass to server. If this data is passed as json string via normal form data then you have to decode it. You'll then get all data in an array.
$.ajax({
type: "POST",
url: "serverUrl",
data: formData,
success: function(){},
dataType: "json",
contentType : "application/json"
});
HTML provides no way to generate JSON from form data.
If you really want to handle it from the client, then you would have to resort to using JavaScript to:
gather your data from the form via DOM
organise it in an object or array
generate JSON with JSON.stringify
POST it with XMLHttpRequest
You'd probably be better off sticking to application/x-www-form-urlencoded data and processing that on the server instead of JSON. Your form doesn't have any complicated hierarchy that would benefit from a JSON data structure.
Update in response to major rewrite of the question…
Your JS has no readystatechange handler, so you do nothing with the response
You trigger the JS when the submit button is clicked without cancelling the default behaviour. The browser will submit the form (in the regular way) as soon as the JS function is complete.
Use FormData API
Capture the form data using FormData API formData= new FormData(form)
Convert it into JSON using JSON.stringify(Object.fromEntries(formData))
Send this strigified json as ajax payload
var form = document.getElementById('myForm');
form.onsubmit = function(event){
var xhr = new XMLHttpRequest();
var formData = new FormData(form);
//open the request
xhr.open('POST','http://localhost:7000/tests/v1.0/form')
xhr.setRequestHeader("Content-Type", "application/json");
//send the form data
xhr.send(JSON.stringify(Object.fromEntries(formData)));
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
form.reset(); //reset form after AJAX success or do something else
}
}
//Fail the onsubmit to avoid page refresh.
return false;
}
Taken from an article I wrote here: https://metamug.com/article/html5/ajax-form-submit.html
You can try something like:
<html>
<head>
<title>test</title>
</head>
<body>
<form id="formElem">
<input type="text" name="firstname" value="Karam">
<input type="text" name="lastname" value="Yousef">
<input type="submit">
</form>
<div id="decoded"></div>
<button id="encode">Encode</button>
<div id="encoded"></div>
</body>
<script>
encode.onclick = async (e) => {
let response = await fetch('http://localhost:8482/encode', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
let text = await response.text(); // read response body as text
data = JSON.parse(text);
document.querySelector("#encoded").innerHTML = text;
// document.querySelector("#encoded").innerHTML = `First name = ${data.firstname} <br/>
// Last name = ${data.lastname} <br/>
// Age = ${data.age}`
};
formElem.onsubmit = async (e) => {
e.preventDefault();
var form = document.querySelector("#formElem");
// var form = document.forms[0];
data = {
firstname : form.querySelector('input[name="firstname"]').value,
lastname : form.querySelector('input[name="lastname"]').value,
age : 5
}
let response = await fetch('http://localhost:8482/decode', {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
let text = await response.text(); // read response body as text
document.querySelector("#decoded").innerHTML = text;
};
</script>
</html>
you code is fine but never executed, cause of submit button [type="submit"]
just replace it by type=button
<input value="Submit" type="button" onclick="submitform()">
inside your script;
form is not declared.
let form = document.forms[0];
xhr.open(form.method, form.action, true);
I'm late but I need to say for those who need an object, using only html, there's a way. In some server side frameworks like PHP you can write the follow code:
<form action="myurl" method="POST" name="myForm">
<p><label for="first_name">First Name:</label>
<input type="text" name="name[first]" id="fname"></p>
<p><label for="last_name">Last Name:</label>
<input type="text" name="name[last]" id="lname"></p>
<input value="Submit" type="submit">
</form>
So, we need setup the name of the input as object[property] for got an object. In the above example, we got a data with the follow JSON:
{
"name": {
"first": "some data",
"last": "some data"
}
}
If you want to use pure javascript in 2022...
const ajax = async (config) => {
const request = await fetch(config.url, {
method: config.method,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(config.payload)
});
response = await request.json();
console.log('response', response)
return response
}
// usage
response = ajax({
method: 'POST',
url: 'example.com',
payload: {"name": "Stackoverflow"}
})
The micro-library field-assist does exactly that: collectValues(formElement) will return a normalized json from the input fields (that means, also, checkboxes as booleans, selects as strings,etc).
I found a way to pass a JSON message using only a HTML form.
This example is for GraphQL but it will work for any endpoint that is expecting a JSON message.
GrapqhQL by default expects a parameter called operations where you can add your query or mutation in JSON format. In this specific case I am invoking this query which is requesting to get allUsers and return the userId of each user.
{
allUsers
{
userId
}
}
I am using a text input to demonstrate how to use it, but you can change it for a hidden input to hide the query from the user.
<html>
<body>
<form method="post" action="http://localhost:8080/graphql">
<input type="text" name="operations" value="{"query": "{ allUsers { userId } }", "variables": {}}"/>
<input type="submit" />
</form>
</body>
</html>
In order to make this dynamic you will need JS to transport the values of the text fields to the query string before submitting your form. Anyway I found this approach very interesting. Hope it helps.
Related
If I have a form like this,
<form action="/Car/Edit/17" id="myForm" method="post" name="myForm"> ... </form>
how can I submit it without redirecting to another view by JavaScript/jQuery?
I read plenty of answers from Stack Overflow, but all of them redirect me to the view returned by the POST function.
You can achieve that by redirecting the form's action to an invisible <iframe>. It doesn't require any JavaScript or any other type of scripts.
<iframe name="dummyframe" id="dummyframe" style="display: none;"></iframe>
<form action="submitscript.php" target="dummyframe">
<!-- Form body here -->
</form>
In order to achieve what you want, you need to use jQuery Ajax as below:
$('#myForm').submit(function(e){
e.preventDefault();
$.ajax({
url: '/Car/Edit/17/',
type: 'post',
data:$('#myForm').serialize(),
success:function(){
// Whatever you want to do after the form is successfully submitted
}
});
});
Also try this one:
function SubForm(e){
e.preventDefault();
var url = $(this).closest('form').attr('action'),
data = $(this).closest('form').serialize();
$.ajax({
url: url,
type: 'post',
data: data,
success: function(){
// Whatever you want to do after the form is successfully submitted
}
});
}
Final solution
This worked flawlessly. I call this function from Html.ActionLink(...)
function SubForm (){
$.ajax({
url: '/Person/Edit/#Model.Id/',
type: 'post',
data: $('#myForm').serialize(),
success: function(){
alert("worked");
}
});
}
Since all current answers use jQuery or tricks with iframe, figured there is no harm to add method with just plain JavaScript:
function formSubmit(event) {
var url = "/post/url/here";
var request = new XMLHttpRequest();
request.open('POST', url, true);
request.onload = function() { // request successful
// we can use server response to our request now
console.log(request.responseText);
};
request.onerror = function() {
// request failed
};
request.send(new FormData(event.target)); // create FormData from form that triggered event
event.preventDefault();
}
// and you can attach form submit event like this for example
function attachFormSubmitEvent(formId){
document.getElementById(formId).addEventListener("submit", formSubmit);
}
Place a hidden iFrame at the bottom of your page and target it in your form:
<iframe name="hiddenFrame" width="0" height="0" border="0" style="display: none;"></iframe>
<form action="/Car/Edit/17" id="myForm" method="post" name="myForm" target="hiddenFrame"> ... </form>
Quick and easy. Keep in mind that while the target attribute is still widely supported (and supported in HTML5), it was deprecated in HTML 4.01.
So you really should be using Ajax to future-proof.
Okay, I'm not going to tell you a magical way of doing it because there isn't.
If you have an action attribute set for a form element, it will redirect.
If you don't want it to redirect simply don't set any action and set onsubmit="someFunction();"
In your someFunction() you do whatever you want, (with AJAX or not) and in the ending, you add return false; to tell the browser not to submit the form...
One-liner solution as of 2020, if your data is not meant to be sent as multipart/form-data or application/x-www-form-urlencoded:
<form onsubmit='return false'>
<!-- ... -->
</form>
You need Ajax to make it happen. Something like this:
$(document).ready(function(){
$("#myform").on('submit', function(){
var name = $("#name").val();
var email = $("#email").val();
var password = $("#password").val();
var contact = $("#contact").val();
var dataString = 'name1=' + name + '&email1=' + email + '&password1=' + password + '&contact1=' + contact;
if(name=='' || email=='' || password=='' || contact=='')
{
alert("Please fill in all fields");
}
else
{
// Ajax code to submit form.
$.ajax({
type: "POST",
url: "ajaxsubmit.php",
data: dataString,
cache: false,
success: function(result){
alert(result);
}
});
}
return false;
});
});
See jQuery's post function.
I would create a button, and set an onClickListener ($('#button').on('click', function(){});), and send the data in the function.
Also, see the preventDefault function, of jQuery!
The desired effect can also be achieved by moving the submit button outside of the form as described here:
Prevent page reload and redirect on form submit ajax/jquery
Like this:
<form id="getPatientsForm">
Enter URL for patient server
<br/><br/>
<input name="forwardToUrl" type="hidden" value="/WEB-INF/jsp/patient/patientList.jsp" />
<input name="patientRootUrl" size="100"></input>
<br/><br/>
</form>
<button onclick="javascript:postGetPatientsForm();">Connect to Server</button>
Using this snippet, you can submit the form and avoid redirection. Instead you can pass the success function as argument and do whatever you want.
function submitForm(form, successFn){
if (form.getAttribute("id") != '' || form.getAttribute("id") != null){
var id = form.getAttribute("id");
} else {
console.log("Form id attribute was not set; the form cannot be serialized");
}
$.ajax({
type: form.method,
url: form.action,
data: $(id).serializeArray(),
dataType: "json",
success: successFn,
//error: errorFn(data)
});
}
And then just do:
var formElement = document.getElementById("yourForm");
submitForm(formElement, function() {
console.log("Form submitted");
});
Fire and forget vanilla js + svelte
function handleSubmit(e) {
const request = new Request(`/products/${item.ItemCode}?_method=PUT`, {
method: 'POST',
body: new FormData(e.target),
});
fetch(request)
}
Used in Svelte:
<form method="post" on:submit|preventDefault={handleSubmit}>
If you control the back end, then use something like response.redirect instead of response.send.
You can create custom HTML pages for this or just redirect to something you already have.
In Express.js:
const handler = (req, res) => {
const { body } = req
handleResponse(body)
.then(data => {
console.log(data)
res.redirect('https://yoursite.com/ok.html')
})
.catch(err => {
console.log(err)
res.redirect('https://yoursite.com/err.html')
})
}
...
app.post('/endpoint', handler)
I am trying to make a form where there will be user data(name,dob etc) and an image. When user submits the form a pdf will be generated with the user given data and the image. I can successfully serialize the data but failed to get image in my pdf. I am using simple ajax post method to post data. Below is my code.
HTML code
<form onsubmit="submitMe(event)" method="POST" id="cform">
<input type="text" name="name" placeholder="Your Name" required>
<input type="file" name="pic" id="pic" accept="image/*" onchange="ValidateInput(this);" required>
<input type="submit" value="Preview"/>
</form>
Jquery code
function submitMe(event) {
event.preventDefault();
jQuery(function($)
{
var query = $('#cform').serialize();
var url = 'ajax_form.php';
$.post(url, query, function () {
$('#ifr').attr('src',"http://docs.google.com/gview?url=http://someurl/temp.pdf&embedded=true");
});
});
}
PHP code
<?php
$name=$_POST['name'];
$image1=$_FILES['pic']['name'];
?>
Here I am not getting image1 value. I want to get the url of the image.
You need FormData to achieve it.
SOURCE
Additionally, you need to change some stuff inside ajax call(explained in link above)
contentType: false
cache: false
processData:false
So the full call would be:
$(document).on('change','.pic-upload',uploadProfilePic);
#.pic-upload is input type=file
function uploadProfilePic(e){
var newpic = e.target.files;
var actual = new FormData();
actual.append('file', newpic[0]);
var newpic = e.target.files;
var actual = new FormData();
actual.append('file', newpic[0]);
$.ajax({
type:"POST",
url:"uploadpic.php",
data: actual,
contentType: false,
cache: false,
processData:false,
dataType:"json",
success: function (response){
#Maybe return link to new image on successful call
}
});
}
Then in PHP you handle it like this:
$_FILES['file']['name']
since you named it 'file' here:
actual.append('file', newpic[0]);
I made a custom Jquery plugin to help me easily send data via Ajax to the server that has been tailored to suit laravel, but apparently I am not able to send any data. when I use dd($request->all()) to check what has been sent to the laravel server, I receive an empty array in console implying that I have not sent anything. Below is my code
JS
(function($){
'use strict'
$.fn.lajax=function(options){
//overwrite options
var optns=$.extend({
dataType: 'json',
debug:false,
processData: true,
headers:{
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
acceptedInputFile:'/*/',
//functions that are very similar to the ajax optns but differ a little
//as the paramters give easy access to the ajax form element
lajaxBeforeSend: function(form,formData,jqXHR,settings){},
lajaxSuccess: function(form,formData,data,textStatus,jqXHR){},
lajaxError: function(form,formData,jqXHR,textStatus,errorThrown){},
},options);
//loop through every form, 'this' refers to the jquery object (which should be a list of from elements)
this.each(function(index,el){
$(el).submit(function(e){
//prevent submission
e.preventDefault();
//form jquery instance & form data
var $form=$(this);
var formData = new FormData($form[0]);
//catch url where the ajax function is supposed to go
var url=$form.attr('action');
//check if REST based method is assigned
if($form.find('input[name="_method"]').length)
{
var method=$(this).find(':input[name="_method"]').val().toUpperCase();
if(optns.debug)
console.log("'"+method+"' method registered for form submission");
}
//If no REST method is assigned, then check method attr
else if($form.attr('method'))
{
var method=$form.attr('method').toUpperCase();
if(optns.debug)
console.log("'"+method+"' method registered for form submission");
}
//method is not assigned
else
{
var method='GET';
if(optns.debug)
console.log('The form that submitted has no method type assigned. GET method will be assigned as default');
}
//object that will be fed into jquerys ajax method
var ajax_options={
url: url,
method: method,
beforeSend: function(jqXHR,settings){
console.log(jqXHR);
console.log(settings);
if(optns.debug)
console.log('executing beforeSend function');
optns.lajaxBeforeSend($form,formData,jqXHR,settings);
},
success: function(data,textStatus,jqXHR){
if(optns.debug)
console.log('executing success function');
optns.lajaxSuccess($form,formData,data,textStatus,jqXHR)
},
error: function(jqXHR,textStatus,errorThrown){
if(optns.debug)
console.log('error encountered. ajax error function procked');
optns.lajaxError($form,formData,jqXHR,textStatus,errorThrown);
var errors = jqXHR.responseJSON;
console.log(errors);
},
}
//check if files are included in the submitted form if the method is not GET
if($form.find('input:file').length && method!='GET'){
ajax_options.processData=false;
ajax_options.contentType=false;
ajax_options.cache=false;
ajax_options.data=formData;
}
if(optns.debug)
console.log('About to send ajax request');
//sending request here
$.ajax(ajax_options);
if(optns.debug)
console.log('finished with form '+$form+'. Looping to next form if exists');
return false;
});
});
return this;
}
}(jQuery));
HTML
<form class="lajax" action="{{ action('AlbumController#store') }}" method="POST" enctype="multipart/form-data">
<div class="form-group">
<label>Album Name</label>
<input type="text" name="name" class="form-control">
</div>
<div class="form-group">
<label for="coverFile">Album Cover Image</label>
<input name="cover" type="file" id="coverFile">
<p class="help-block">Example block-level help text here.</p>
</div>
<div class="form-group">
<label for="albumFiles">Album Images</label>
<input type="file" name="photos[]" multiple>
</div>
<button type="submit" class="btn btn-primary">Create Album</button>
</form>
I think my JS is not sending my data over to the server but im not sure why. Please help
Did you define a Post route in your route file that exactly point to AlbumController#store Controller method
I am trying to send some data via POST method to a PHP file without using form in HTML. This is the code I have. Why doesn't it do anything?
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="hidden" value="<?php echo $row['Gallery_Id']; ?>" name="gid" id="gid">
<input type="hidden" value="User" name="user" id="user">
<button onclick="myFormData()">Upload Image</button>
<script>
$('#fileToUpload').on('change', function() {
var myFormData = new FormData();
var file = document.getElementById('fileToUpload').value;
var gid = document.getElementById('gid').value;
var user = document.getElementById('user').value;
myFormData.append('file', file);
myFormData.append('gid', gid);
myFormData.append('user', user);
});
$.ajax({
url: 'imgupload.php',
type: 'POST',
processData: false, // important
contentType: false, // important
dataType : 'json',
data: myFormData
});
</script>
On imgupload.php I get the POST data like this
$gid = $_POST['gid'];
$user = $_POST['user'];
It worked when I used the HTML form method. What's wrong here?
FormData.append() takes key-value pairs, so this is wrong:
myFormData.append(file,gid,user);
You need something like:
myFormData.append('file', file);
myFormData.append('gid', gid);
myFormData.append('user', user);
Appart from that you need to put this code inside an event handler so that it triggers when you need it to.
For example:
$('#fileToUpload').on('change', function() {
// your javascript code
});
And you should probably also put it inside a document.ready block.
Hi i have create a JSON object getting data from a form and now i want to POST that into redmine API. This is what i have done so far.
<script>
// This is the creation of JSON object
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return {"project":o};
};
// This is the API linking and POSTING
$(document).ready(function(){
$("#submit").on('click', function(){
// send ajax
$.ajax({
url: 'http://localhost/redmine/projects.json', // url where to submit the request
type : "post", // type of action POST || GET
dataType : 'jsonp',
headers: { 'X-Redmine-API-Key': 'admin' },
data : JSON.stringify($('form').serializeObject()), // post data || get data
success : function(result) {
// you can see the result from the console
// tab of the developer tools
alert("Sucess");
console.log(result);
},
error: function(xhr, resp, text) {
console.log(xhr, resp, text);
}
})
});
});
</script>
<form action="" method="post">
First Name:<input type="text" name="name" maxlength="12" size="12"/> <br/>
Last Name:<input type="text" name="identifier" maxlength="36" size="12"/> <br/>
<!-- number:<input type="number" name="number" maxlength="36" size="12"/> <br/> -->
<textarea wrap="physical" cols="20" name="description" rows="5">Enter your favorite quote!</textarea><br/>
<p><input type="submit" /></p>
</form>
The post doesn't work. JSON object is created well, Passing that to API is the problem. I think problem is here,
data : JSON.stringify($('form').serializeObject()),
How do i pass the created JSON Object above to data. Thanks
You can not use POST and custom headers with jsonp. What jsonp does to work across different domains is basically inserting a <script> tag that calls a callback when finished, e.g.
<script src="different.domain/api/projects.json?callback=done123"></script>
function done123 (result) {
// do something with result
}
The server (if it supports a jsonp call) then returns JavaScript (not JSON!) that looks like this:
done123({"name1":"val1","name2":{"name3":true,"name4":5}})
Which calls your function when done and works cross-domain because it uses a script tag.
If you run the script from the same domain that redmine is running, change the dataType: 'jsonp' to json. Depending on how redmine expects you to send the data (JSON-body vs. form-data), you might need to change the data value:
// When redmine API expects JSON post body
data : JSON.stringify($('form').serializeObject()),
// When redmine API expects multipart POST data
data : $('form').serializeObject()