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が終わってからリダイレクトされます。
次は削除ボタンを作ります。