Home > Blockchain >  Sending data in a html form to mysql data base using express results in undefined database columns
Sending data in a html form to mysql data base using express results in undefined database columns

Time:01-13

My main goal is to create a RestAPI with Node.js and test it in small HTML application.

My teacher helped us create the RestAPI with an example, and I was able to adapt it to my own MySQL database, and I have tested every endpoint of the API using Thunder Client extension on Visual Studio Code, and it is working correctly.

However I am having problems in the testing of the html app. I am trying to send some data using a form, but as i submit it doesn't save any of the data i put in the form, instead, it inserts null values to all columns. I know the endpoint it is right, because it truly connects to the right function and table, and inserts new data rows to the table.

Here is my HTML form

<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
   
    <title>Header</title>

    <link rel="stylesheet" href="css/styles.css">
    </head>
<body>

    <h1 id="teste"> Adicionar um Videojogo</h1>
    <form action=" http://localhost:3000/api/videogames" method="post" enctype="multipart/form-data"  >

        <div  id="form_">
                    <input type="text" name= "nome" id="nome" placeholder="Nome" required= "required">
                    </div>
        <div  id="form_">
                    <input type="text" name= "produtora" id="produtora" placeholder="Produtora" required= "required">               
                    </div>
        <div  id="form_">
                   <input type="text" name= "distribuidora" id="distribuidora" placeholder="Distribuidora" required= "required">
                    </div>
        <div  id="form_">
                   <input type="text" name= "ano" id="ano" placeholder="Ano" required= "required">
    
                   </div>

Here is my model:

const sql = require("./db.js");

// construtor
const Videogame = function(videogame) {
  this.nome = videogame.nome;
  this.produtora = videogame.produtora;
  this.distribuidora = videogame.distribuidora;
  this.ano = videogame.ano;
  this.id_genero= videogame.id_genero;
  this.id_plataforma = videogame.id_plataforma;
}

Videogame.insert = (newVideogame, result) => {
  sql.query('INSERT INTO videogame SET ?', newVideogame, (err, res) => {
    if (err) {
      console.log('error: ', err);
      result(err, null);
      return;
    }

    console.log("Videojogo inserido: ", { id: res.insertId, ...newVideogame });
    result(null, { id: res.insertId, ...newVideogame});
  });
}

My Controller:

const Videogame = require("../models/videogame.model.js");

// Inserir um novo videojogo
exports.insert = (req, res) => {
    // Validar a request
    if (!req.body) {
      res.status(400).send({
        message: "O conteúdo do videojogo deve estar definido."
      });
    }
  
    // Criar um "Videogame"
    const videogame = new Videogame({
      nome: req.body.nome,
      produtora: req.body.produtora,
      distribuidora: req.body.distribuidora,
      ano: req.body.ano,
      id_genero: req.body.id_genero,
      id_plataforma: req.body.id_plataforma,
    });
  
    // Guardar "Videogame" na base de dados
    Videogame.insert(videogame, (err, data) => {
      if (err)
        res.status(500).send({
          message:
            err.message || "Ocorreu um erro ao inserir o videojogo..."
        });
      else res.send(data);
           
    });
  };

My routes:

module.exports = app => {
    const videogames = require("../controllers/videogame.controller.js");
  
    var router = require("express").Router();
  
    // Consultar todos os videojogos
    router.get("/", videogames.selectAll);
  
    // Consultar um videojogos pelo id
    router.get("/:id", videogames.findById);
  
    // Inserir um novo videojogo
    router.post("/", videogames.insert);
  
    // Atualizar um videojogo pelo id
    router.put("/:id", videogames.update);
  
    // Apagar um videojogo pelo id
    router.delete("/:id", videogames.delete);
  
    // Apagar todos os videojogos
    router.delete("/", videogames.deleteAll);
  
    app.use('/api/videogames', router);
  };

My server:

const express = require('express');
const cors = require('cors');

const app = express();
const PORT = process.env.PORT || 3000;
const corsOptions = {
  origin: 'http://localhost'
};

app.use(cors(corsOptions));

// tratamento (parse) de pedidos de content-type - application/json
app.use(express.json());

// tratamento (parse) de pedidos de content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));

/*// route de "entrada" - apenas para efeito de teste
app.get("/", (req, res) => {
  res.json({ message: "Movies API . IPVC" });
});*/

// importação das videogames.routes com um argumento de inicialização
require('./app/routes/videogames.routes.js')(app);

// ativação do servidor, onde serão recebidos os pedidos, na porta definida
app.listen(PORT, () => {
  console.log(`Servidor ativo na porta ${PORT}.`);
});

It connects to the database , but here is the DB connection anyway

const mysql = require('mysql');
const DBConfig = require('../config/db.config.js');

// Criar conexão à base de dados
const connection = mysql.createConnection({
  host: DBConfig.DBSERVER,
  user: DBConfig.DBUSER,
  password: DBConfig.DBPASS,
  database: DBConfig.DBNAME
});

// Abrir conexão à base de dados
connection.connect(error => {
  if (error) throw error;
  console.log('Ligação à base de dados estabelecida...');
});

module.exports = connection;

Here is the result that appear on the terminal, after i submit my form

Videojogo inserido:  {
  id: 14,
  nome: undefined,
  produtora: undefined,
  distribuidora: undefined,
  ano: undefined,
  id_genero: undefined,
  id_plataforma: undefined
}

It should save the data I from the form instead of undefined (I also have 2 radio buttons for id_genero and id_plataforma in my form, but I only put the other inputs here, because I don't think the problem is with the radio buttons, as if it were, it would assign the other input values in forms.)

CodePudding user response:

You're using express.json() but your form data is not in JSON format.

You can install express-formidable with npm in your app folder

Then you need to create the middleware using it, like so:

// in app.js
const formidableMiddleware = require('express-formidable');
//...

// Note that req.fields will be instead of req.body due to middleware
// used to handle json, forms, and uploading files
app.use(formidableMiddleware(
  {
    encoding: 'utf-8',
    // means multi files (array of files) in one request
    multiples: true, 
  }
));

You will need to replace app.use(express.json()); with above snippet

You can also check an example from ExpressJS repo on github for multipart forms

CodePudding user response:

I don't know how you set up your server, but you should have a middleware to parse the incoming data. for HTML form data you will need to use the following app.use(express.urlencoded({ extended: false }));

You can read here to learn more about express built-in middleware and their optional properties.

Also just noticed that you are using enctype="multipart/form-data", is there any reason for that? Your form looks basic enough so you should be able to use application/x-www-form-urlencoded which is the default, so you won't need to specify it.

  •  Tags:  
  • Related