I know I can take post data from WordPress / PHP and pass it into JS by using AJAX. But is it possible to do this the other way round? i.e. create a JS event listener on a form and the pass the values back to the server to be executed using a PHP function.
Yes, definietly. You pretty much answerd the question yourself.Here is some code to get you started.
document.querySelector(".whateverFormSubmit").click(function(e){
e.preventDefault();
let formInfo = document.querySelector("input1");
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.querySelector("response").innerHTML = this.responseText;
}
};
xhttp.open("POST", "ajax.php", true);
xhttp.send('formInfo=' + formInfo);
})
Pay attention to preventDefault(), if you don't use it your form will be posted through HTTP body, thus rendering your AJAX useless.
And there you go, you posted information from frontend to backend without refreshing the page. Of course you can mess around with sending a JSON, but I kept it simple.
Related
I'm a client-side newbie learning the ropes, and need to clarify Ajax concepts.
e.preventDefault(); is a typical method of preventing form submission (page refresh) in JS.
One use case where the above is handy is Ajax-based form submission. Sample code is:
function overwrite_default_submit(e) {
// block the default behavior
e.preventDefault();
// create and populate the form with data
var form_data = new FormData();
form_data.append("reply", text_field.value);
// send the form via AJAX
var xhr = new XMLHttpRequest();
xhr.open('POST', e.target.action);
xhr.setRequestHeader("X-CSRFToken", get_cookie('csrftoken'));
xhr.send(form_data);
}
I have two questions:
1) Imagine the POST request is being sent to a function that ends with a redirect to a different URL. For example, I use Django to develop web applications; a typical Django view may end up with return redirect("home") where home is the home page of the said app. In such a scenario, how does preventDefault() prevent the redirect statement in server-side code from executing? I'm trying to understand the exact mechanics behind it.
2) What if one wanted page refresh (or redirect) to proceed normally after an Ajax POST request? What tweaks need to be made? Would love to see an illustrative example to clarify my concepts.
I'm well-versed in Django (Python) so in case you need to show server-side code, Django would be a good example.
Note: prefer to stick to pure JS for this, since I'm learning JS these days. JQuery's on my radar, but only after I've mastered the fundamentals of JS.
The preventDefault() cancels the event, Default action that event of element will not occur. This will simply halt further execution of javascript code after that statement.
For i.e.
- Clicking on a submit button, prevent it from submitting a form.
- Clicking on a link, prevent the link from following the given
URL
To redirect to the next page or to add notification or may be to add html through javascript, but here is to redirect only.
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) //Here we need to check OK response and last state of ajax call.
{
window.location.href = 'REDIRECT_URL'
window.location.reload() // To refresh page.
}
};
=== I've added that in your function ===
function overwrite_default_submit(e)
{
// block the default behavior
e.preventDefault();
// create and populate the form with data
var form_data = new FormData();
form_data.append("reply", text_field.value);
// send the form via AJAX
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) //Here we need to check OK response and last state of ajax call.
{
window.location.href = 'REDIRECT_URL'
window.location.reload() // To refresh page.
}
};
xhr.open('POST', e.target.action);
xhr.setRequestHeader("X-CSRFToken", get_cookie('csrftoken'));
//xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(form_data);
}
Now in case of Django you need also need to add view / call proper action that should return either json or xml.
from django.http import JsonResponse
def some_view(request):
return JsonResponse({"key": "value"})
To know how ajax work you can check here https://www.w3schools.com/xml/ajax_intro.asp
1) Ajax request should not receive redirect response. Usually it supposed to be a valid json-string. Django has a JsonResponse for this purpose. If you want your django view to process ajax data you should check it on your backend side, for example:
if request.is_ajax():
return JsonResponse({'data': data})
2) You can do redirect with your javascript code, for instance:
window.location.href = 'https://stackoverflow.com'
I have a site that makes an HTTP request for JSON data, then a callback function processes the data and displays it by creating a series of divs dynamically. What I want to do is to wait for that function to finish adding the divs to the page, then apply labels only to specific divs created by the previous code.
HTTP Request and Callback
function data(callback){
var url = //request url;
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState === 4) {
if (request.status === 200) {
document.body.className = 'ok';
//Parse returned string into an object, then pass the object to the callback function.
var data = JSON.parse(request.responseText);
callback(data);
} else {
document.body.className = 'error';
}
}
};
request.open("GET", url , true);
request.send(null);
}
function dataDisplay(data){
//outputs <div id="1064" class="displayed-data">
<p id="message1" class="hidden"></p>
}
data(dataDisplay);
The code above displays my data exactly how I want it to, but when I try to access the numbered ID of the divs I want to change, the function runs before the data is displayed on the page, causing a 'null' error because the data I am trying to change hasn't been added to the DOM yet.
Second Function to change original
function label(){
var message1 = document.createTextNode('//some label');
var displayedData = document.getElementById('1064').getElementById('message1');
displayedData.appendChild(message1);
document.getElementById('message1').classList.remove('hidden');
}
How do I get the second function to wait until the callback has completed before trying to access and change it? I tried a callback inside of a callback, something like: label(data(dataDisplay)); but it still threw the same errors, so I clearly did it wrong. Sorry, I am brand new to JavaScript and don't really know where to go from here.
Thanks for your help!
A pretty quick way of doing it correctly is with this inline function.
data(function(result) {
dataDisplay(result);
label();
});
Be aware that your data function itself completes very quickly - if you need something from its result, you will need to include it in its callback.
I'm very new at this. I've read books to learn javascript and HTML, so unfortunately I haven't learn much about this.
I never used AJAX before, so not sure how it works, searched online, but find all examples too complicated.
Basically what I want to do is save a playlist (although not with cookies). Something everyone can see and add-on to it (similarly to a comments section).
This is just an example, I'm doing something else, but the html + js would be a bit big. Just want to know how I would do it on this, so that I could understand it (hopefully) and apply it elsewhere.
This would be the body and below it the code I have (currently all my code is in [head]):
<body>
<form>
<input type="text" id="songInput" size="40" placeholder="Song Name">
<img id="addButton" src="button.png">
</form>
<ul id="playlist"></ul>
</body>
<script>
window.onload = load;
function load() {
var button = document.getElementById("addButton");
button.onclick = buttonClick;
}
function buttonClick() {
var text = document.getElementById("songInput");
var song = text.value;
var button = document.getElementById("addButton");
var add = document.createElement("li");
add.innerHTML = song;
var ul = document.getElementById("playlist");
ul.appendChild(add);
}
</script>
First you have to understand what AJAX is. AJAX is not a "tool" that you can use, instead, it's a name for the techniques (asynchronous JavaScript + XML). Basically it means "getting/posting data from/to server."
In vallina JavaScript, XMLHttpRequest lets you send and receive data to and from a server:
var xhr = new XMLHttpRequest(); //Create an XMLHttpRequest object
xhr.open('get', url); //Set the type and URL
xhr.onreadystatechange = function(){ //Tell it what to do with the data when state
// changes
if(xhr.readyState === 4){ //4 is the code for "finished"
if(xhr.status === 200){ //Code 200 means "OK"
//success
var data = xhr.responseText; //Your data
}else{
//error //Deal with errors here
}
}
};
xhr.send(null); //After finished setting everything, send the
// request. null here means we are not send-
// ing anything to the server
It might look complicated, and xhr is repeated quite a lot. Not to mention the problems that we have to deal with when executing in IE.
There is solution for that. We will use libraries to simplify the process and let it do the hard works for us.
In jQuery, this is what you have to do to for a basic XMLHttpRequest:
$.ajax({
url: url,
data: { /*data here*/ },
type: /*"GET" or "POST"*/
}).done(function(data){
//success
}).fail(function(){
//error
});
//Not complicated at all with jQuery
Since AJAX is a group of techniques to send/receive data, there're more ways to do the "same" thing. You might realize the code above only works for URL that has the same domain (pages on your server). To bypass that limitation, there's another technique called JSONP. Sounds fancy, but what it means is simply "using the <script> tag to get pass that limitation". And of course, jQuery got you covered:
$.ajax({
url: url,
data: { /*data here*/ },
type: /*"GET" or "POST"*/,
dataType: "JSONP" //specifying dataType to be JSONP
}).done(function(data){
//success
});
Here is a simple example of getting content off Wikipedia using JSONP: http://jsfiddle.net/DerekL/dp8vtjvt/
With a normal XMLHttpRequest call to Wikipedia's server would not work. However by exploiting the fact that script tags are not restricted by the Same-Origin Policy we can achieve the same thing. Note that for JSONP to work, the server must be programmed internally to allow returning a JSON with wrapped callback call.
I am using the easybitcoin.php script here:
(It makes json-rpc calls to bitcoind)
I've made a seperate php file, that retrieves the data from the easybitcoin.php file such as balance, accounts..etc. And spits it out on a page.
When making a json-RPC call, such as:
retrieve_once('easybitcoin.php');
print_r($<username>->getbalance($_SESSION['username']) );
You need to refresh the page to get your updated balance, how would you make it dynamic where the user does not have to refresh the page.
Thanks for any help.
Make an AJAX GET request:
var client = new XMLHttpRequest();
client.onreadystatechange = handler;
client.open("GET", "yourPhpFile.php");
client.send();
Create the handler:
function processData(data) {
// taking care of data
}
function handler() {
if(this.readyState == this.DONE) {
if(this.status == 200 &&
this.responseXML != null) {
// success!
processData(this.responseXML);
return;
}
// something went wrong
processData(null);
}
}
In the processData function do whatever you want with the data you receive from the server.
In the yourPhpFile.php you should include the easybitcoin.php file and make the necessary calls.
Now you can encapsulate your AJAX request in setInterval(), this way it will periodically get updates.
I'm fairly new to ajax but am trying to implement two simple calls to dynamically changes two separate divs on a page using javascript. I have no problems using one call at a time, but when I use two it seems like the second xmlhttprequest takes over the first and writes into both divs.
I've read and tried using the fixes listed on these two other posts both neither seem to work in my case:
Sending two Ajax requests to two different PHP scripts from single javascript function
Using two xmlhttprequest calls on a page
And here is my relevant code:
function request_handler(url, params, changed_div) {
if(window.XMLHttpRequest) {
try {
req = new XMLHttpRequest();
}catch(e) {
req = false;
}
}else if(window.ActiveXObject) {
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
}catch(e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){
req = false;
}
}
}
if(req) {
req.onreadystatechange = function(){
if (req.readyState == 4 && req.status == 200){
document.getElementById(changed_div).innerHTML = req.responseText);
}
}
req.open("POST", url, true);
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.send(params)
return true;
}
return false;
}
Here is the basic format of each request using the function above:
request_handler("sample.php", parameters , "sample_div");
Apologies if I'm passing something simple up here, I just can't seem to get it to work.
This question
Using two xmlhttprequest calls on a page
does answer your question.
In your request_handler function, you're using a global variable req that gets overwritten every time you call that function.
If you change it to start:
function request_handler(url, params, changed_div) {
var req;
// Rest of your function
}
you should find that it works. In this case req has a local scope and so is not overwritten when you call request_handler for the second time.
Can I also suggest that you strongly consider using the likes of jQuery, Prototype or Dojo, if you're planning on writing Ajax scripts? Writing scripts that work cross-browsers is hard to do well and these frameworks do a lot of the legwork for you.
Your req is a global variable as it is defined without the var keyword, keep that in mind.
What I think happens is that the second call overwrites the first one. This is because of the (default) asynchronous nature of the XMLHTTPRequest. Your first function call will end, but the fetching of the page is still going. The second function call then overwrites the previous request.
This however does not explain why both div get filled with the result of the second call. I must say I'm a bit lost on that one.
This is a pretty common problem, especially if you don't want to take additional measures to block further calls until the first has finished loading. Its a bigger subject that I can cover in a post but there are several examples on the web of an "Ajax Queue" that effectively manages the order of requests received.
jQuery has a plugin for managing queues and I'm certain that most other JavaScript frameworks such as Prototype and MooTools will as well. If you're wanting to stick with raw JavaScript I would take a look at this web page:
http://www.cmarshall.net/MySoftware/ajax/index.html
He implements a queue very effectively and has an excellent example of its use.