0

I am in the process of learning web development and am just picking up AJAX; and this quest to learning AJAX is driving me crazy...

I've seen a lot of similar posts on stackoverflow using JQuery, but I am looking to achieve this using plain JS.

My requirement is that, I have an HTML page that posts form data via the XMLHTTPRequest object. The data is sent correctly to the sever (Node). What I would like to achieve is to reload the same page that sent the data with the data that it just posted (Like So).

I know this can be done through JQuery (ie. via a call to location.reload()), however I cannot get this to work simply by using XHMHTTPRequest. Is it even possible to achieve this with XHR? I can see that the xhr's ResponseText has the entire HTML with the desired update (See Ref). How can I then use this html to reload the page.

Any directions are greatly appreciated.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge, chrome=1"/>

<script>
"use strict";
function submitForm()
{
  var formElement = document.getElementById("myForm");
  var formData = new FormData(formElement);

  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange=function(){
    if (xhr.readyState == 4 && xhr.status == 200)
    {
      alert(xhr.responseText); //xhr.responseText has the entire desired HTML
      window.location.reload; //Does nothing
    }
  }
  xhr.open("POST", "/Test", true);
  xhr.send(formData);
  return false;
}
</script>
</head>

<body>
<form id="myForm" method="POST" action="/Test" onsubmit="return submitForm()">
   <input type="text" value="John" name="name"/>
   <input type="submit" value="Send Data"/>
</form>
<div class="">
  <h4>Name entered was <%= data %></h4>
</div>
</body>
</html>
//Node JS
var express = require('express');
var bodyparser = require('body-parser');
var multer = require('multer'); 

var app = express();
app.use(express.static('./'));
app.set('view engine', 'ejs');
var mydata;

var urlencoded = bodyparser.urlencoded({extended:true});
var mult_handler = multer();

app.get('/Test', function(req, res){
    res.render("Test", {data:mydata});
});

app.post('/Test',mult_handler.none(), function(req, res){
  console.log("In POST");
  console.log(req.body.name);
  mydata = req.body.name;
  res.render("Test", {data:req.body.name});
});
Laavanya
  • 5
  • 1
  • 1
    This is not how AJAX is purposed to be used, use a regular form to reload the page. `location.reload()` is not jQuery, it's just a pure DOM object and its method. – Teemu Mar 10 '20 at 18:49
  • Sidenote: jQuery is a library written in JavaScript, so anything done with jQuery can be done in vanilla JavaScript. And if you want, you can use the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) instead of XMLHttpRequest. – Domino Mar 10 '20 at 18:52
  • You aren't calling the reload function. You didn't put parens after `window.location.reload` – Domino Mar 10 '20 at 18:55
  • `window.location.reload` just reloads the page, anything returned from the XHR is not available on that new page. – Teemu Mar 10 '20 at 18:58

1 Answers1

0

Here's a high level answer building off of Teemu's comment. I agree in that this isn't how AJAX is meant to be used. The whole purpose of using AJAX is so that you do NOT need to refresh the page to load the data from the request. Rather, you can dynamically display data/content from each request.

Currently, in your code where you have this:

alert(xhr.responseText); //xhr.responseText has the entire desired HTML
window.location.reload; //Does nothing

Try removing the window.location.reload and parsing xhr.responseText in a way that works for your application. And what that means is that you should parse it depending on what your endpoint is returning. A quick way to return JSON in your /Test endpoint is by writing res.send({ data: req.body.name }); at the end of your app.post() statement. There are other ways to return json which is more relevant to Express.js than this question, so I won't go into detail.

And once you parsed the data from the XHR object that is returned to the client-side, you can select different elements on your page by id and update their values. There's many ways to update values but that's just one of them.

For instance, you can write your sample div like this:

<div>
  <h4 id="some_text"></h4>
</div>

And use vanilla JS to add a value to the h4 tag in your statechanged handler. Perhaps something like this: document.getElementById("some_text").innerHtml = JSON.parse(xhr.responseText).data;

Jackson
  • 53
  • 1
  • 8
  • @Teemu: Thanks for your comment. Since I know this can be achieved via jOquery and also since jQuery is basically vanilla JS under the hood, I got a little curious with trying to work this out with vanilla Js and XHR. How does one use the XHR.responseText though, if it returns the HTML of interest that one needs to load.? – Laavanya Mar 11 '20 at 08:19
  • @Domino: I'll give the FetchAPI a shot, even with a parenthesis around location.reload() i couldn't get it to work. – Laavanya Mar 11 '20 at 08:19
  • Jackson, thanks a lot for your comment. This clears a lot of things for me. So, if i were to be redirecting the POST to another page, with updated data, would a res.render("SomeotherPageWithUpdatedData", {data:req.body.name}); work, provided the action attribute is also pointing to the same page? – Laavanya Mar 11 '20 at 08:38
  • @Laavanya No, jQuery doesn't load a new page using the fetched data either. If the response is a HTML string, then you can use it directly as a value of `innerHTML`, the idea of XHR is specifically, that only a part of the page will be repopulated with some new content. If you really must create a totally new page from the response, [here is how to do that](https://stackoverflow.com/a/59711118/1169519), though I don't recommend such a huge misuse of XHR in any circumstances, because the same can be achieved by using a simple form submission instead of the AJAX call. – Teemu Mar 11 '20 at 08:50
  • Again, I agree with Teemu's response in that only if you really have to create a totally new page, then you should use a form submission instead of a XHR. Since I'm assuming you're creating your own custom endpoint to call, you can just return a JSON object which will make your `xhr.responseText` hold a JSON value. I don't think using `res.render()` would work here as under my understanding, `res.render()` is for rendering an entire page/view. Docs: `Renders a view and sends the rendered HTML string to the client` But you can try `res.json()`: https://expressjs.com/en/api.html#res.json – Jackson Mar 11 '20 at 18:05