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.
