Sending HTML Form Multiple <select> box via POST request with AJAX? - javascript

I have an html form with a multiple select box. I can't figure out how to send the values to my php application with AJAX via a post request. It works just fine if I use a GET request and use a single select box but not when I use a multiple select box. The idea is for users to hold control (or command with mac) and select one or more categories. Depending on which categories are selected will determine what other form options will be displayed using AJAX. The select box looks like this:
Edit: SOLVED
<select multiple name="categories[]" onclick="sendCategories(this)">
<option value="0">Category 1</option>
<option value="1">Category 2</option>
<option value="2">Category 3</option>
</select>
My javascript function looks like this:
function sendCategories(sel){
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
else
{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("my_div").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("POST","http://www.mysite.com/update_categories.php",true);
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
var values = $(sel).serialize();
xmlhttp.send(values);
}

You'll have to generate the query string to send in the POST on your own. Here's the HTML tag to use:
<select multiple name="categories[]" onchange="sendCategories(this);">
And the Javascript function:
function sendCategories(sel){
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
document.getElementById("my_div").innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("POST","http://www.mysite.com/update_categories.php",true);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var values = [], i, j, cur;
for (i = 0, j = sel.options.length; i < j; i++) {
cur = sel.options[i];
if (cur.selected) {
values.push(encodeURIComponent(cur.value));
}
}
if (values.length) {
values = encodeURIComponent(sel.name) + "=" + values.join("&" + encodeURIComponent(sel.name) + "=");
} else {
values = null;
}
xmlhttp.send(values);
}
Note that I changed the event from onclick to onchange, but that's really up to you whether you want this function to run when the element is clicked, or its value is truly changed...it can reduce some unnecessary calls.
This should generate a querystring that is normally used for sending values for a <select> with multiple options selected.
Here's a jsFiddle that demonstrates how the querystring is being generated here: http://jsfiddle.net/kKWQM/

You can do something like this,
<select multiple name="categories[]" onclick="sendCategories(this)">
And Make AJAX using JQuery,
function sendCategories(sel){
var values = $(select).serialize();
console.log (values); // See if you get the serialized data in console.
$.ajax({
type: 'POST',
url: "http://www.mysite.com/update_categories.php"
data: values,
success: function (data) {
document.getElementById("my_div").innerHTML = data;
}
});
}
And FYI, Netscape event binding model is deprecated, you could use the cross browser event binding like this

You can implement the solution however you would like using JS string and array functions. Effectively, the string you need to send to Apache should contain a pattern like:
xxx[]=a&xxx[]=b&xxx[]=c
where the SELECT element's name is xxx[] in your form and a, b, and c are three values the user selected.
So yes, you are repeating a key name as many times as the user selected a different option in the SELECT.
In JS you can use an array of selected options:
selected_options.join("&xxx[]=") to produce that pattern.

jQuery should make this easier for you. Calling .val() on a wrapped select returns an array of the selected values. You just have to post these to the server:
HTML:
<html>
<body>
<form>
<select name="mySelect" multiple="on">
<option value="1">Uno</option>
<option value="2">Dos</option>
<option value="3">Tres</option>
</select>
</form>
<input id="submitButton" type="button" value="Click To Submit"/>
</body>
</html>
JavaScript:
$(function() {
$('#submitButton').click(function() {
var valuesArray = $('select[name=mySelect]').val()
$.ajax({
type: 'POST',
url: '/path/to/php', // your php url would go here
data: { mySelect: valuesArray }
}).done(function(msg) {
// parse response from msg
});
});
});

Related

jquery placeholder while ajax loads dropdown menu

I have a 2 dropdowns, one with a list of countries and one with a list of states. When someone clicks a country, the state dropdown is changed to reflect the ones for that country.
The country dropdown is like this:
<select name="country" id="country" onChange = "states_dropdown(this, 0)">
<option value="001" >United States</option>
<option value="002" >Canada</option>
<option value="003" >Mexico</option>
</select>
And the states/provinces like this:
<select name="state" id="state">
<option value="00101" >Alabama</option>
<option value="00102" >Alaska</option>
<option value="00103" >Arizona</option>
</select>
Obviously, the states change when someone changes the country, with this code:
function state_box(country, user_id) {
var xmlHttp = GetXmlHttpObject();
if (xmlHttp == null) {
alert("Browser does not support HTTP Request");
return;
}
var url = relative_path + 'ajax/states.php';
var action = url + '?country_id=' + country.value;
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
document.getElementById('state').innerHTML = xmlHttp.responseText;
}
};
xmlHttp.open("GET", action, true);
xmlHttp.send(null);
}
This all works fine, but the actual problem is that while the server processes the request, the states of the currently selected or default country remain visible. So if someone clicks really fast, he could choose Mexico as the country and Alabama as the state.
The ajax/jquery script states.php that loads the states returns just the option values, that's all.
Is there a way to make it so that while it's loading, it would display:
<option value="">Please wait</option>
and maybe even make the entire box as "disabled" to prevent someone from selecting it?
You can set the dropdown to show a waiting option as the new data loads, you can place this before you make the ajax request.
document.getElementById('state').innerHTML = '<option value="">Please wait</option>';
You can also just disable the dropdown, the advantage of this is that it is reversable(in case the request didn't succeed)
document.getElementById('state').disabled = true;
xmlHttp.onreadystatechange = function() {
if (this.readyState == 4) {
document.getElementById('state').disabled = false;
if (this.status == 200){
document.getElementById('state').innerHTML = this.responseText;
}
}
};
function state_box(country, user_id) {
var xmlHttp = GetXmlHttpObject();
if (xmlHttp == null) {
alert("Browser does not support HTTP Request");
return;
}
var url = relative_path + 'ajax/states.php';
var action = url + '?country_id=' + country.value;
var selectBox = document.getElementById('state'); // save the reference to the element
selectBox.innerHTML = '<option value="">Please wait</option>';
selectBox.disabled = true; // disable the select
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
selectBox.innerHTML = xmlHttp.responseText;
selectBox.disabled = false; // enable the select
}
};
xmlHttp.open("GET", action, true);
xmlHttp.send(null);
}
provided the responseText is something like this <option value="00101">city 1</option><option value="00102">city 2</option><option value="00103">city 2</option>
check out this fiddle for reference here

Multiple XMLHttpRequests not working

I am puzzled about this. I have two XMLHttpRequests that operate on Select elements of my HTML file (each one operates on a different Select element right when the HTML file is loaded). I am using a callback function as was recommended on W3CSchools. If my variable xmlHttp is defined outside of my callback function, only the second request works, and the first one gets deleted before it has a chance to finish. If I put 'var' in front of it the same thing happens. However, if my variable is inside the function with 'var' in front of it, then absolutely nothing happens. I have narrowed it down to where to the line that says "HERE!!!!!" is where the program seems to hang. I know the loadXMLDoc function does not actually finish because when I put an alert outside of it, nothing happens. I am supposing it has something to do with the 'if' part and the program not being able to recognize xmlHTTP, even though it was locally defined. I am still pretty new to JavaScript and just want to be able to run multiple XMLHttpRequest objects at once without them getting in each other's way but also without the page hanging. Any ideas why this does not work?
HTML:
<form>
<select id="stateSelectCities">
<!-- Will be populated with MySQL -->
</select>
<select id="citySelect">
<option>Select a State</option>
</select>
<br />
<br />
<select id="stateSelectCounties">
<!-- Will be populated with MySQL -->
</select>
<select id="countySelect">
<option>Select a State</option>
</select>
<p id="xmltest"></p>
<p id="currentState"></p>
<p id="sc"></p>
<p id="rs"></p>
<p id="st"></p>
</form>
JavaScript:
<script type="text/javascript">
function loadXMLDoc(method, data, url, cfunc) {
var xmlHTTP = new XMLHttpRequest();
xmlHTTP.onreadystatechange = cfunc;
xmlHTTP.open(method, url, true);
if (data) {
xmlHTTP.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlHTTP.send(data);
} else {
xmlHTTP.send();
}
}
function returnStateListForCounties() {
loadXMLDoc('GET', null, "stateslist.xml", function() {
document.getElementById('countySelect').disabled = true;
if (xmlHTTP.readyState == 4 && xmlHTTP.status == 200) {
// Read the XML Data and Populate Counties States Menu
var response = xmlHTTP.responseXML;
var states = response.getElementsByTagName('state');
for (i = 0; i < states.length; i++) {
var option = document.createElement('option');
option.innerHTML = states[i].childNodes[0].nodeValue;
option.setAttribute('onmouseup', 'returnCounties(this.innerHTML)');
document.getElementById("stateSelectCounties").add(option);
}
}
//document.getElementById("sc").innerHTML = 'statusCode: ' + xmlHTTP.status;
//document.getElementById("rs").innerHTML = 'readyState: ' + xmlHTTP.readyState;
//document.getElementById("st").innerHTML = 'statusText: ' + xmlHTTP.statusText;
})
}
function returnStateListForCities() {
loadXMLDoc('GET', null, 'stateslist.xml', function() {
document.getElementById('citySelect').disabled = true;
// HERE!!!!!
if (xmlHTTP.readyState == 4 && xmlHTTP.status == 200) {
// Read the XML Data and Populate Cities States Menu
var response = xmlHTTP.responseXML;
var states = response.getElementsByTagName('state');
for (i = 0; i < states.length; i++) {
var option = document.createElement('option');
option.innerHTML = states[i].childNodes[0].nodeValue;
option.setAttribute('onmouseup', 'returnCities(this.innerHTML)');
document.getElementById("stateSelectCities").add(option);
}
}
document.getElementById("sc").innerHTML = 'statusCode: ' + xmlHTTP.status;
document.getElementById("rs").innerHTML = 'readyState: ' + xmlHTTP.readyState;
document.getElementById("st").innerHTML = 'statusText: ' + xmlHTTP.statusText;
})
}
//returnStateListForCounties();
returnStateListForCities();
</script>
The problem here is xmlHTTP variable which is defined inside loadXMLDoc function and try to use again inside returnStateListForCounties function, I'll do it like this:
function loadXMLDoc(method, data, url, cfunc) {
var xmlHTTP = new XMLHttpRequest();
xmlHTTP.onreadystatechange = function() {
if (xmlHTTP.readyState == 4 && xmlHTTP.status == 200)
{
cfunc(xmlHTTP.responseXML); //Call passed func with the resulting XML
}
};
xmlHTTP.open(method, url, true);
if (data) {
xmlHTTP.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlHTTP.send(data);
} else {
xmlHTTP.send();
}
}
This way you encapsulate the data recovery.

XMLHttpRequest to Post HTML Form

Current Setup
I have an HTML form like so.
<form id="demo-form" action="post-handler.php" method="POST">
<input type="text" name="name" value="previousValue"/>
<button type="submit" name="action" value="dosomething">Update</button>
</form>
I may have many of these forms on a page.
My Question
How do I submit this form asynchronously and not get redirected or refresh the page? I know how to use XMLHttpRequest. The issue I have is retrieving the data from the HTML in javascript to then put into a post request string. Here is the method I'm currently using for my zXMLHttpRequest`'s.
function getHttpRequest() {
var xmlhttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
} else {// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
return xmlhttp;
}
function demoRequest() {
var request = getHttpRequest();
request.onreadystatechange=function() {
if (request.readyState == 4 && request.status == 200) {
console.log("Response Received");
}
}
request.open("POST","post-handler.php",true);
request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
request.send("action=dosomething");
}
So for example, say the javascript method demoRequest() was called when the form's submit button was clicked, how do I access the form's values from this method to then add it to the XMLHttpRequest?
EDIT
Trying to implement a solution from an answer below I have modified my form like so.
<form id="demo-form">
<input type="text" name="name" value="previousValue"/>
<button type="submit" name="action" value="dosomething" onClick="demoRequest()">Update</button>
</form>
However, on clicking the button, it's still trying to redirect me (to where I'm unsure) and my method isn't called?
Button Event Listener
document.getElementById('updateBtn').addEventListener('click', function (evt) {
evt.preventDefault();
// Do something
updateProperties();
return false;
});
The POST string format is the following:
name=value&name2=value2&name3=value3
So you have to grab all names, their values and put them into that format.
You can either iterate all input elements or get specific ones by calling document.getElementById().
Warning: You have to use encodeURIComponent() for all names and especially for the values so that possible & contained in the strings do not break the format.
Example:
var input = document.getElementById("my-input-id");
var inputData = encodeURIComponent(input.value);
request.send("action=dosomething&" + input.name + "=" + inputData);
Another far simpler option would be to use FormData objects. Such an object can hold name and value pairs.
Luckily, we can construct a FormData object from an existing form and we can send it it directly to XMLHttpRequest's method send():
var formData = new FormData( document.getElementById("my-form-id") );
xhr.send(formData);
The ComFreek's answer is correct but a complete example is missing.
Therefore I have wrote an extremely simplified working snippet:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge, chrome=1"/>
<script>
"use strict";
function submitForm(oFormElement)
{
var xhr = new XMLHttpRequest();
xhr.onload = function(){ alert(xhr.responseText); }
xhr.open(oFormElement.method, oFormElement.getAttribute("action"));
xhr.send(new FormData(oFormElement));
return false;
}
</script>
</head>
<body>
<form method="POST"
action="post-handler.php"
onsubmit="return submitForm(this);" >
<input type="text" value="previousValue" name="name"/>
<input type="submit" value="Update"/>
</form>
</body>
</html>
This snippet is basic and cannot use GET. I have been inspired from the excellent Mozilla Documentation. Have a deeper read of this MDN documentation to do more. See also this answer using formAction.
By the way I have used the following code to submit form in ajax request.
$('form[id=demo-form]').submit(function (event) {
if (request) {
request.abort();
}
// setup some local variables
var $form = $(this);
// let's select and cache all the fields
var $inputs = $form.find("input, select, button, textarea");
// serialize the data in the form
var serializedData = $form.serialize();
// fire off the request to specific url
var request = $.ajax({
url : "URL TO POST FORM",
type: "post",
data: serializedData
});
// callback handler that will be called on success
request.done(function (response, textStatus, jqXHR){
});
// callback handler that will be called on failure
request.fail(function (jqXHR, textStatus, errorThrown){
});
// callback handler that will be called regardless
// if the request failed or succeeded
request.always(function () {
// reenable the inputs
});
// prevent default posting of form
event.preventDefault();
});
With pure Javascript, you just want something like:
var val = document.getElementById("inputFieldID").value;
You want to compose a data object that has key-value pairs, kind of like
name=John&lastName=Smith&age=3
Then send it with request.send("name=John&lastName=Smith&age=3");
I have had this problem too, I think.
I have a input element with a button. The onclick method of the button uses XMLHTTPRequest to POST a request to the server, all coded in the JavaScript.
When I wrapped the input and the button in a form the form's action property was used. The button was not type=submit which form my reading of HTML standard (https://html.spec.whatwg.org/#attributes-for-form-submission) it should be.
But I solved it by overriding the form.onsubmit method like so:
form.onsubmit = function(E){return false;}
I was using FireFox developer edition and chromium 38.0.2125.111 Ubuntu 14.04 (290379) (64-bit).
function postt(){
var http = new XMLHttpRequest();
var y = document.getElementById("user").value;
var z = document.getElementById("pass").value;
var postdata= "username=y&password=z"; //Probably need the escape method for values here, like you did
http.open("POST", "chat.php", true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", postdata.length);
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(postdata);
}
how can I post the values of y and z here from the form

Receiving NULL in parameter when passing from js to Servlet.

I am getting null when trying to receive parameter from JavaScript. I have gone through few post, but could not figure out where i am making the mistake in my code.
Below is code from where i am sending request:
function funcOnChange() {
var index = document.detail.Class.selectedIndex;
var valueSelected = document.detail.Class.options[index].value;
handleRequestStateChange = function()
{
// Check to see if this state change was "request complete", and
// there was no server error (404 Not Found, 500 Server Error, etc)
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
var substring=xmlHttp.responseText;
alert("Alert Dialog! Gaurav");
}
}
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:8080/ReportFetcher/FormHandler', true);
xhr.send(valueSelected);
}
I am getting the valueselected from the following piece of code and valueselected's is correct:
<select name="Class" onchange="funcOnChange()">
<option value="None">None</option>
<option value="FIRST">FIRST</option>
<option value="SECOND">SECOND</option>
<option value="THIRD">THIRD</option>
<option value="FOURTH">FOURTH</option>
<option value="FIFTH">FIFTH</option>
<option value="SIXTH">SIXTH</option>
<option value="SEVENTH">SEVENTH</option>
<option value="EIGHTH">EIGHTH</option>
<option value="NINTH">NINTH</option>
<option value="TENTH">TENTH</option>
</select><br>
I am receiving a callback on onPost() of FormHandler.java
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
log.info("IN form doPost");
String selectedClass = request.getParameter("Class");
log.info(selectedClass);
}
Problem: selectedClass is null here.
Suggest where i am making mistake.
try this
function funcOnChange() {
var index = document.detail.Class.selectedIndex;
var valueSelected = "Class="+document.detail.Class.options[index].text;
.....
.....
xhr.send(valueSelected);
}
If you see through any proxy/ HTTP monitor tool ( I use Charles) your requests and responses you will see that you are not sending the request as key value pairs ( in simple terms you are not sending Class=value) but you are sending only the value of Class attribute as string. (i.e. Third if you select the option Third in the select box). You need to send the FormData if you want to read data on server as key value pairs.
function funcOnChange() {
var index = document.detail.Class.selectedIndex;
var valueSelected = document.detail.Class.options[index].value;
handleRequestStateChange = function()
{
// Check to see if this state change was "request complete", and
// there was no server error (404 Not Found, 500 Server Error, etc)
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
var substring=xmlHttp.responseText;
alert("Alert Dialog! Gaurav");
}
}
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://fiddle.jshell.net/', true);
var form = new FormData();
form.append("Class",valueSelected)
xhr.send(form);
}

Twig and javascript

i'm creating a page that shows a chart depending on the type selected in the combo box
<div id="chartdiv"></div>
<select name="graphe" id="identifiantDeMonSelect">
<option value="Column2D">Column2D
<option value="Column3D">Column3D
<option value="Pie3D">Pie3D
<option value="Pie2D">Pie2D
</select>
<input type="submit" value="Afficher" onclick="ajax()">
<script type="text/javascript">
function ajax(){
var xhr
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
if (xhr !=null) {
xhr.onreadystatechange = function() { type1(xhr); };
xhr.open("GET", "{{ path('Ajax')}}", true);
xhr.send(null);
} else {
alert("The XMLHttpRequest not supported");
}}
function type1(xhr){
var docXML= xhr.responseText;
var val_type = getSelectValue('identifiantDeMonSelect');
var type = val_type+"";
var str="{{ asset('Charts/Pie2D.swf') }}";
var chart = new FusionCharts(str, "ChartId", "600", "400", "0", "0");
chart.setXMLData(docXML);
chart.render("chartdiv");
}
function getSelectValue(selectId)
{
var selectElmt = document.getElementById(selectId);
return selectElmt.options[selectElmt.selectedIndex].value;
}
</script>
Now when i simply replace var str="{{ asset('Charts/Pie2D.swf') }}"; with "{{asset('Charts/'+type+'.swf') }}" in order to dynamically change the the type of the chart i obtain the following symfony error : "Variable "type" does not exist in ". And when i put "{{ asset('Charts/"+type+".swf') }}" (i just replaced ' by ") i get the page and when i click the submit button nothing happens, and inside the console (chrome's console) i get this error "GET http://127.0.0.1:8888/dashboard2/Symfony/web/Charts/"+type+".swf 404 (Not Found) ". It takes it as it is "+type+"
Obviously i need help, i don't know if it's a concatenation problem or it has something to do with the twig and the asset function. Thanks in advance
I guess that is not possible. you cant mix javascript vars with twig because one is client the other is server.
Instead of using {{asset}} here you could make a route to fetch your asset and use asset functionality in the action.
you then can use this:
https://github.com/FriendsOfSymfony/FOSJsRoutingBundle
or a cheap workaround like this:
route = "{{ path('myassetroute', { 'pie': "PLACEHOLDER" }) }}";
route = route.replace("PLACEHOLDER", type);

Categories