Reputation: 69
Passing an object to Pug from app.js
router.get('/', getMenuList, function (req, res, next) {
res.render('menu_items', {
title: 'The Weekly Menu',
message: 'The List',
dataset
});
});
The dataset looks like
menu_date dish_name Display
2018-10-01 Fish 2018-10-01: Fish
2018-10-01 Green Beans 2018-10-01: Green Beans with Mushrooms and cream
2018-10-02 Out To Dinner 2018-10-02: Out To Dinner
2018-10-03 Oysters 2018-10-03: Oysters an the half shell
2018-10-03 Sauce Mignette 2018-10-03: Sauce Mignette
What I want to display on HTML is a nested list like
2018-10-01
Fish
Green Beans
2018-10-02
Out to diner
2018-10-03
Oysters
Sauce Mignette
My PUG code as follows iterates over the object but I don't know how to get nested list
extends layout
block content
h2= title
-var wtf = dataset.length
-var n = 0
h1= message
each item in dataset
ul
li #{item.Menu_Date}
Posted below is the app.js which writes an html page. The code is ugly. Not facile with javascript, HTML, or CSS.
//submit
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
var tedious = require('tedious');
var Promise = require('promise');
app.use(bodyParser.urlencoded({ extended: false }));
var path = require('path');
var fs = require('fs');
var router = express.Router();
var menu_data = [];
var menu = [];
app.engine('pug', require('pug').__express);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(router);
app.use(express.static(path.join(__dirname, 'public')));
router.get('/', getMenuList, function (req, res, next) {
var item = [];
for(var row of menu_data ){
if(menu.length == 0) {
var newItem = {Date: row.MenuDate, Items: item};
menu.push(newItem);
}
if(row.MenuDate != menu[menu.length -1].Date) {
item = [];
var newItem = {Date: row.MenuDate, Items: item};
menu.push(newItem);
}
var newDish = {Dish: row.Item};
menu[menu.length -1].Items.push(row.Item);
/* var i = 0;
while(i < menu[menu.length -1].Items.length) {
console.log( menu[menu.length -1].Items[i]);
i++;
}
*/
}
fs.writeFileSync('./views/message.html', '<!DOCTYPE html><html><head><title>The Weekly Menu</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body>', 'utf8', function(err){
if (err) throw err;
});
fs.appendFileSync('./views/message.html', '<h1>Why the drama</h1>', function(err){
if (err) throw err;
});
for(index = 0; index < menu.length ; index++ ) {
//console.log(menu[index].Date);
if(index ===0){
fs.appendFileSync('./views/message.html', '\r\n<ul>', function(err){
if(err) throw err;
});
}
fs.appendFileSync('./views/message.html', '\r\n<li>' + menu[index].Date + '</li>', function(err){
if(err) throw err;
});
for(newindex = 0; newindex < menu[index].Items.length; newindex++) {
//console.log(menu[index].Items[newindex])
if(newindex === 0 ){
fs.appendFileSync('./views/message.html','\r\n<ul>', function(err){
if(err) throw err;
});
}
fs.appendFileSync('./views/message.html', '\r\n<li> ' + menu[index].Items[newindex] + '</li>', function(err){
if(err) throw err;
});
}
fs.appendFileSync('./views/message.html', '\r\n</ul', function(err){
if(err) throw err;
});
} // end of outer loop
fs.appendFileSync('./views/message.html', '\r\n</ul>\r\n\<a href=\"http://localhost:3030/index\"> Input Menu Items</a>\r\n</body>\r\n</html>', function(err){
if(err) throw err;
});
/* res.render('menu_items', {
title: 'The Weekly Menu',
message: 'The List',
menu_data,
menu
}); */
res.sendfile('./views/message.html');
});
router.get('/index', function(req, res) {
res.render('index')
});
router.post('/update',submitMenuItem, function (req, res) {
var menu_data = req.body.menuDate;
var description = req.body.theItem;
res.render('update', {
title: 'All Quiet on the Western Front',
menuDate: menu_data,
MenuItem: description
});
});
// end of submitMenuItem
function getMenuList( req, res, next) {
var promise = new Promise(function(fulfill, reject){
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var config = JSON.parse(fs.readFileSync('./config/config.json', 'utf8'));
var connection = new Connection(config);
connection.on('connect', function (err) {
if (err) {
console.log(err);
} else {
executeStatement();
}
});
/* function MenuItem(Menu_Date, Name, Display)
{
this.Menu_Data = Menu_Date;
this.Name = Name;
this.Display = Display;
} */
function executeStatement() {
var sql = "select dt_ofItem ,dish_name FROM LA_COUNTY.dbo.mn_items order by dt_ofItem";
var Request = require('tedious').Request;
request = new Request(sql, function (err, rowCount) {
if (err) {
reject(err);
} else {
if(rowCount < 1) {
callback(null, false);
}
else {
fulfill(menu_data);
}
}
});
request.on('row', function (columns) {
var Menu_Date = ""
columns.forEach(function (column) {
if(column.metadata.colName=== "dt_ofItem"){
Menu_Date = column.value.toDateString();
}
if(column.metadata.colName==="dish_name") {
//console.log(column.value);
//console.log('WTF');
//var item = new MenuItem(Menu_Date, column.value, Menu_Date + ": " + column.value);
var menu_stuff = {
MenuDate: Menu_Date,
Item: column.value
};
menu_data.push(menu_stuff);
//menu_data.push("Date" Menu_Date ,"Item" column.value );
//item = null;
}
});
});
request.on('doneProc', function (rowCount, more, returnStatus, rows) {
next(null, rows);
connection.close()
// console.log(menu_data[0].MenuDate);
menu_data = [];
});
connection.execSql(request);
}
});
} // end getclients
function submitMenuItem( req, res, next) {
var menu_date = req.body.menuDate;
var description = req.body.theItem;
var Connection = require('tedious').Connection;
var config = JSON.parse(fs.readFileSync('./config/config.json', 'utf8'));
var connection = new Connection(config);
var connection = new Connection(config);
connection.on('connect', function(err) {
executeStatement();
});
function executeStatement() {
var sql = "insert LA_County.dbo.mn_items (dt_ofItem, dish_name) values ('" + menu_date + "','" + description + "')"
var Request = require('tedious').Request;
request = new Request(sql, function(err, rowCount) {
if (err) {
reject(err);
} else {
if(rowCount < 1) {
callback (null, false);
}
else {
fulfill(menu_date);
}
}
});
request.on('row', function(columns) {
columns.forEach(function(column) {
//console.log(column.value);
});
});
request.on('doneProc', function (rowCount, more, returnStatus, rows) {
next(null, rows);
connection.close()
});
connection.execSql(request);
}
} // end of submitMenuItem
here is the PUG code. Which I am very very unsure about
extends layout
block content
h2= title
-var wtf = menu_data.length
//h1 #{wtf}
-var n = 0
h1= message
ul
while n < wtf
li= menu_data[n++].MenuDate
ul
each entry in menu
li= entry.Date
-var i = entry.Items.length
h3 #{i}
-var q = 0
ul
each dish in entry.Items
li dish
//while q < i
//li= entry.Items[q]
a(href='http://localhost:3030/index') Input Menu Items
app.listen(3030);
module.exports = app;
For a more complete view the code is on GIT
Sorry if I am not doing these posts according to Hoyle.
Upvotes: 4
Views: 4558
Reputation: 7802
In order to get this working you'll need to massage your data a little bit in the route.
We'll create an array of objects with the date as the keys and an array of dishes as the properties for each date. We want to use an array as the core object as key order is not guaranteed iterating JavaScript objects, but it is in arrays.
Doing this will make it easy for the Pug template to iterate through and give you the nested list you want. Adding complex conversion logic into the template itself isn't a good idea, the route is the best place to store that.
Here is the pug-friendly array that we'll want to dynamically build:
[
{
"date": "2018-10-01",
"items": ["Fish", "Green Beans"]
},
{
"date": "2018-10-02",
"items": ["Out to Diner"]
},
{
"date": "2018-10-03",
"items": ["Oysters", "Sauce Mignette"]
}
]
Here's how to convert it (I'm assuming your dataset variable is sorted here, if not then you'll need to use a different algorithm to do this):
var menu = [];
for(var row of dataset){
// see if the date on the current row is the same as the last date in the menu array
if( row.menu_date != menu[menu.length - 1].date ) {
// add new object to the end of the array
menu.push({
"date": row.menu_date,
"items": []
});
}
// add item from current row to the end of the array in the last menu date entry
menu[menu.length - 1].items.push(row.dish_name);
}
Pass the menu variable into the res.render function instead of the dataset, then the template can iterate through this object like this:
ul
each entry in menu
li= entry.date
ul
each item in entry.items
li= item
If you ever need to change the logic here (adding fields, changing list format, etc.) or debug your code, keeping the template simpler makes it very easy.
Upvotes: 4