Steffen Laurens
Steffen Laurens

Reputation: 41

POST request via AJAX (Vanilla JavaScript) produce empty object on Node.js (express/body-parser/ejs)

I'm having difficulties sending post request using AJAX with Vanilla Javascript. Everytime I post a request it always print an empty object on the server console, I tried to check (console.log) the object before it being sent and it seems okay, but somehow the server only receives an empy object. When I try sending post req with jquery the object print out on the server the way it should (I'll attach both codes down below). I've tried reading other users' postings but I can't seem to find out the problem. Here's my code:

Vanilla JS:

<script>
    document.getElementById('postForm').addEventListener('submit', postName);

    function postName(event) {
        event.preventDefault();

        var item = document.getElementById('item').value;
        var todo = {
            item: item
        };

        var xhr = new XMLHttpRequest();
        xhr.open('POST', '/todo', true);
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded parser');

        xhr.onload = function () {
            location.reload();
            console.log(todo);
            console.log(this.responseText);
        }

        xhr.send(todo);
    }
</script>

and here's the jquery version:

$(document).ready(function(){

  $('form').on('submit', function(){

    var item = $('form input');
    var todo = {item: item.val()};

    $.ajax({
      type: 'POST',
      url: '/todo',
      data: todo,
      success: function(data){
        //do something with the data via front-end framework
        location.reload();
      }
    });

    return false;

  });

});

Server code:

var bodyParser = require('body-parser');
var data = [{item: 'get milk'}, {item: 'walk dog'}, {item: 'kick some coding ass'}];
var urlencodedParser = bodyParser.urlencoded({extended: false});

module.exports = function(app) {
    app.get('/todo', function(req, res) {
        res.render('todo', {todos: data});
    });
    app.post('/todo', urlencodedParser, function(req, res) {
        console.log(req.body);
        data.push(req.body);
        res.json(data);
    });
};

App.js:

var express = require('express');
var todoController = require('./controllers/todoController');

var app = express();

// set up template engine
app.set('view engine', 'ejs');

// static files
app.use(express.static('./public'));

// fire controllers
todoController(app);

// listen to port
app.listen(3000);
console.log('You are listening to port 3000');

Upvotes: 1

Views: 1771

Answers (2)

Dr4kk0nnys
Dr4kk0nnys

Reputation: 765

A great way to also solve this, when you're trying to send data though vanilla javascript to a backend server that is running express and node, is with the following:

First, on the main file of the backend ( where you have the app.listen() ), add the following:

// Configs.
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

On the routes/whatever.js file ( the one you will handle the post request ), you'll want to check for the body of the request:

router.post("/", (req, res) => {
    const { the, variables, you, expect } = req.body;
    // Add a try block to check the variables and treat errors ( or handle it the way you like
});

Now to send the data through vanilla javascript:

function sendPostData(data) {
    /*
        @param: data
            Data will be a string containing the name of the file that shall be created.
            Ex: data = "database.txt"
    */
    const xhr = new XMLHttpRequest();
    xhr.open("POST", "http://localhost:8000/", true);

    /*
        * Note that we're using application/json instead of application/x-www-form-urlencoded parser
    */
    xhr.setRequestHeader("Content-type", "application/json"); 

    xhr.send(JSON.stringify({"data": data}));
    console.log(xhr.responseText);
}

Upvotes: 2

Mr. Ratnadeep
Mr. Ratnadeep

Reputation: 621

Tried with your code you just need to include app.use(bodyParser.json()). It will work

app.js

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var index = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);

app.get('/todo', function(req, res) {
    res.render('todo', {todos: data});
});

app.post('/todo', function(req, res) {
    console.log(req.body);
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

index.ejs

<!DOCTYPE html>
<html>
  <head>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <form  method="post">
      <input type="text"/>
      <input type="submit"/>
    </form>
    <script
            src="https://code.jquery.com/jquery-3.3.1.min.js"
            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
            crossorigin="anonymous"></script>
  <script>
      $(document).ready(function(){

          $('form').on('submit', function(){

              var item = $('form input');
              var todo = {item: item.val()};

              $.ajax({
                  type: 'POST',
                  url: '/todo',
                  data: todo,
                  success: function(data){
                      //do something with the data via front-end framework
                      location.reload();
                  }
              });
              return false;
          });
      });
  </script>
  </body>
</html>

Upvotes: 0

Related Questions