简体   繁体   中英

How to refresh form page after POST request?

I'm working on a single page website using Netbeans (HTML5 with Node.js and Express JS). The following is a sample of what I need to do (Not the real website).

I have a form, when I click submit, I need it to post data to DB and refresh the current page that has the form. Right now it posts the data to DB and displays blank page (looks like empty JSON formatted page. The reason I need to refresh is I'm creating REST APIs to display data from the same DB on the same page (index.pug).

In my case I'm using Jage/Pug instead of HTML files

//index.pug
form(method='post', class="form-signin")
    input(type='text',class="form-control", name='fname')
    input(type='text',class="form-control", name='lname')
    button#button(type='submit', value='Submit') ADD

Here is app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const bodyParser = require("body-parser");
const pg = require('pg');
const config = {
user: 'postgres',
database: 'postgres',
    password: 'password',
    port: 5432,
    idleTimeoutMillis: 30000// (30 seconds) how long a client is allowed to remain idle before connection being closed
};
const pool = new pg.Pool(config);

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

var app = express();

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

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

app.use(function(req, res, next){ //This is so I can use the pool in routes js files
        req.pool = pool;
        next();
    });

app.use('/', indexRouter);
app.use('/users', usersRouter);

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

// catch 404 and forward to error handler
app.use(function(req, res, next) {
   next(createError(404));
});


// 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;

and here is routes/index.js

var express = require('express');
var router = express.Router();
const bodyParser = require("body-parser");

router.use(bodyParser.urlencoded({extended: true}));
router.use(bodyParser.json());

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
    });
//post to database
router.post("/",function (req, res, next) {
    // Grab data from http request
    var pool = req.pool;
    const data = {fname: req.body.fname, lname: req.body.lname};

 pool.connect(function (err, client, done) {
       if (err) {
           console.log("Can not connect to the DB" + err);
           res.status(400).send(err);
           }
           client.query('INSERT INTO public.names(fname, lname) values($1, $2)', [data.fname.toUpperCase(), data.lname.toUpperCase()],
              function (err, result) {
                done();
                if (err) {
                    console.log(err);
                    res.status(400).send(err);
                }
                res.status(200).send(result.rows);
                //res.redirect(req.get('referer'));
           });
        });
    });
//Create an API display all
router.get("/api/all", function (req, res, next) {
    var pool = req.pool;

    pool.connect(function (err, client, done) {
       if (err) {
           console.log("Can not connect to the DB" + err);
           res.status(400).send(err);
       }
       client.query('SELECT * FROM public.names', function (err, result) {
            done();
            if (err) {
                console.log(err.stack);
                res.status(400).send(err);
            }
            res.status(200).send(result.rows);
       });
    });
  });

module.exports = router;

I tried doing this in jQuery:

$('#button').click(function() {
        location.reload(true);
    });

It works but only when I click on ADD button without having any values in the input fields.

Is it possible to reload the page after a POST request? Is there anything I'm doing wrong here?

Thank you in advance!

您是否尝试过将动作参数添加到表单中?

form(method='post', class="form-signin", action="/#")

由于按钮是类型submit您不必使用Javascript处理重新加载,因为它是默认的表单提交事件行为。

EDIT: In addition to form-submit which gives away connection and empty browser DOM. In addition to that you are using res.send() which just send away data to browser and since there's no JavaScript in DOM to take care of response and response is displayed with no HTML.

To show result in html render an other ejs with response data.

router/index.js :

//post to database
router.post("/",function (req, res, next) {
  // Grab data from http request
  var pool = req.pool;
  const data = {fname: req.body.fname, lname: req.body.lname};

 pool.connect(function (err, client, done) {
   if (err) {
       console.log("Can not connect to the DB" + err);

       // This is how to display data with html
       res.render('error', {err});
       }
       client.query('INSERT INTO public.names(fname, lname) values($1, $2)', [data.fname.toUpperCase(), data.lname.toUpperCase()],
          function (err, result) {
            done();
            if (err) {
                console.log(err);

                // This is how to display data with html
                res.render('error', {err});
            }

            // This is how to display data with html
            res.render('desplayData', result.rows);
       });
    });
});

error.ejs :

    <!DOCTYPE html>
<html >
    <head>
        <meta charset="UTF-8">    
        <title>Error</title>
    </head>
    <body>
        <p><%=err%></p>
    </body>
</html>

displayData.ejs :

    <!DOCTYPE html>
<html >
    <head>
        <meta charset="UTF-8">    
        <title>Display Data</title>
    </head>
    <body>
        <p><%=rows%></p>
    </body>
</html>

Better Approach single-page application using javaScript I don't understand pug/jade so will use html

index.html

<!DOCTYPE html>
<html >
    <head>
        <meta charset="UTF-8">    
        <title>Index</title>
    </head>
    <body>
        <input id="fName" type="text">
        <input id="lName" type="text">
        <p onclick="addInfo()">Submit</p>
        <!-- No need for `form` as will use JavaScript for Single Page Application -->

        <!-- This p tag will display response -->
        <p id="response"></p>

        <!-- This p tag will display error -->
        <p id="error"></p>
        <script type="text/javascript" src="/js/jquery.min.js"></script>
        <script>
             function addInfo() {
                // JavaScript uses `id` to fetch value
                let fName               = $("#fName").val(),
                    lName               = $("#lName").val();

                $.ajax({
                    "url": "/addDetail",
                    "method": "POST",
                    "data": {fName, lName}
                })
                .then( result => {
                    // On success empty all the input fields.
                    $("#fName").val('');
                    $("#lName").val('');
                    // Message to notify success submition
                    alert("Successfully added user.");

                    let newHTML = `<span>` + result + `</span>`;

                    $("#response").html(newHTML);

                    return;
                })
                .catch( err => {
                    // Notify in case some error occured
                    alert("An error occured.");

                    let newHTML = `<span>` + result + `</span>`;

                    $("#error").html(newHTML);

                    return;
                });
            }
        </script>
    </body>
</html>

router/index.js :

//post to database
router.post("/addDetail",function (req, res, next) {
    // Grab data from http request
    var pool = req.pool;
    const data = {fname: req.body.fname, lname: req.body.lname};

     pool.connect(function (err, client, done) {
         if (err) {
             console.log("Can not connect to the DB" + err);
             res.status(400).send(err);
         }
         client.query('INSERT INTO public.names(fname, lname) values($1, $2)', [data.fname.toUpperCase(), data.lname.toUpperCase()],
            function (err, result) {
                done();
                if (err) {
                    console.log(err);
                    res.status(400).send(err);
                 }
                 res.status(200).send(result.rows);
                 //res.redirect(req.get('referer'));
            });
       });
 });

The reason you are seeing empty page with json is you are using form submit which is not a single page application method. In order to stick to same page and just change html content use any JavaScript framework for UI like AngularJs, reactJs, backboneJs etc.

You can also use AJAX call to submit data and stay on same page and display your response from API in same HTML by hiding and displaying different HTML tags.

I have given similar answers in different posts too check all these out:

  1. how to send data to html page and how to use ajax for single page application
  2. how-to-render-a-html-page-form-nodejs-api-when-requested-via-ajax
  3. how-to-fetch-fields-from-request-in-node-js-using-express-framework
  4. how-to-render-a-html-page-form-nodejs-api

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM