stap4.データベースの内容を表示する

step3の続きです。

routes/index.jsに追記します

var express = require('express');
var router = express.Router();

var mongoose = require('mongoose');

var Schema = mongoose.Schema;

var Docs = new Schema({
 name: String,
 age: Number,
 date: {
  default: Date.now,
  type: Date,
 }
});
var todoModel = mongoose.model('docs', Docs);

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

router.post('/insert', function(req, res, next) {
  console.log(req.body);
  var todoObject = new todoModel(req.body);
  todoObject.save();

  res.render('index', { title: 'Express' });
});

module.exports = router;

今回は最終的にすべてルートにリダイレクトして1ページで完結させます。
なので一覧表示はルートに記述します。

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

ここに書き変えていきます。

/* GET home page. */
router.get('/', function(req, res, next) {
  todoModel.find({}, function(err, docs) {
    res.render('index', { docs: docs });
  });
});

こんな感じです。

次にviews/index.ejsに送ったdocsを表示する記述をします。

<!DOCTYPE html>
<html>
  <head>
    <title>ToDoリスト</title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1>ToDoリスト</h1>

    <form action="/insert" method="post">
      <table border="1">
        <tr>
          <th>name(文字列)</th>
          <td><input type="text" name="name" value="" /></td>
        </tr>
        <tr>
          <th>age(数字のみ)</th>
          <td><input type="text" name="age" value="" /></td>
        </tr>
        <tr>
          <th>ボタン</th>
          <td><button>登録</button></td>
        </tr>
      </table>
    </form>
  </body>
</html>

formタグのの下に書き足して行きましょう

<% for (var i = 0; i < docs.length; i++) { %>

<% } %>

上記の記述でdocs配列の長さだけfor分が繰り返されます。
このfor分の中に一覧表示させていきます。

    <table border="1">
      <% for (var i = 0; i < docs.length; i++) { %>
        <tr>
          <th>name</th>
          <td><%- docs[i].name %></td>
          <th>age</th>
          <td><%- docs[i].age %></td>
        </tr>
      <% } %>
    </table>

1つのtableに中身を追加する感じなので上記のような記述になります。

少し成形してindex.ejsの中身は下記のようにしました。

<!DOCTYPE html>
<html>
<head>
<title>ToDoリスト</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1>ToDoリスト</h1>

<form action="/insert" method="post">
<table border="1">
<tr>
<th>name(文字列)</th>
<td><input type="text" name="name" value="" /></td>
</tr>
<tr>
<th>age(数字のみ)</th>
<td><input type="text" name="age" value="" /></td>
</tr>
<tr>
<th>ボタン</th>
<td><button>登録</button></td>
</tr>
</table>
</form>

<hr >

<table border="1">
<% for (var i = 0; i < docs.length; i++) { %>
<tr>
<th>name</th>
<td><%- docs[i].name %></td>
<th>age</th>
<td><%- docs[i].age %></td>
</tr>
<% } %>
</table>

</body>
</html>

新しくデータを追加してみてください。

エラーになると思います。

これはroutes/index.jsの/insertの問題です。

router.post('/insert', function(req, res, next) {
  console.log(req.body);
  var todoObject = new todoModel(req.body);
  todoObject.save();

  res.render('index', { title: 'Express' });
});

ここでres.renderでtitleを渡していますが、titleは既に使っていません。

更にエラーの原因はindex.ejsでdocsの連想配列を使っているせいです。

/insertではdocsの連想配列は渡していません。
なのでejs側でエラーになったわけです。

これを解決するために下記のように記述しても構いません

router.post('/insert', function(req, res, next) {
  console.log(req.body);
  var todoObject = new todoModel(req.body);
  todoObject.save();

  todoModel.find({}, function(err, docs) {
    res.render('index', { docs: docs });
  });
});

ですがもっと簡単な方法があります。

router.post('/insert', function(req, res, next) {
console.log(req.body);
var todoObject = new todoModel(req.body);
todoObject.save();

res.redirect('/');
});

これで自動的にルートのindexページに移動して一覧表示からしてくれます。

基本的に他の機能もリダイレクトさせる方法をとります。

しかしこの方法では100点とは言えません。

このままではデータがsaveしている間にリダイレクトしてしまいます。
これは非同期処理されるためです。
タイミングによってはデータの保存が完了する前にリダイレクト処理が先に走ってしまい。
一覧に表示されない場合があります。

router.post('/insert', function(req, res, next) {
  console.log(req.body);
  var todoObject = new todoModel(req.body);
  todoObject.save(function (err) {
    if (err) return handleError(err);
    res.redirect('/');
  });
});

これでsaveが終わってからリダイレクトされます。

次は削除ボタンを作ります。

あわせて読みたい