Search code examples
javascriptnode.jsajaxexpressbody-parser

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');

Solution

  • 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>