Search code examples
node.jsexpresspug

Error rendering list with Pug and ExpressJS


Hello I am fairly new to Node, express, and pug I am trying to render an object to a view and I am receiving a pug error, Or at least I think it is a pug error. I am using the pugcli and when it tries to render the html I get an error.

The pugcli error is displayed on the terminal as:

Cannot read property 'length' of undefined

This is strange because when I try to view it in the browser even though the pug cli shows an error the browser shows a list but with all the <li> elements empty.

I want the <li> to display the objects id, name,and age

I understand that in pug in order to render an object you have to iterate through it with a for loop of some kind. I have written that in the pug file but the objects do not render.

I would appreciate help about what I am missing in the code or if I completely screwed up the code somehow?

My setup is at follows

bin/www
public
   javascripts
   stylesheets
routes
   index.js
views
   index.pug
   layout.pug
   ...
app.js

My index.pug is:

extends layout
block content
  h1= title
  p Welcome to #{appHeading}
  div
    ul
      for user, i in users
        li= users.name +" - "+ users.id
      li=number

This is my index.js is:

var express = require('express');
var router = express.Router();
var users = [
  {
    id: 0,
    name: 'Glenn',
    age: 40
  },
  {
    id: 1,
    name: 'Jeff',
    age: 37
  },
  {
    id: 2,
    name: 'Sara',
    age: 22
  },
  {
    id: 3,
    name: 'Bill',
    age: 41
  },
  {
    id: 4,
    name: 'Mary',
    age: 29
  },

];
var appHeading = 'my object render app ' 
var number = 42;
/* GET home page. */
router.get('/', function(req, res, next) {

  //res.json(users);
  //res.send('Is this working?')
  res.render('index', { 
    title: 'This is my app to render objects in pug',
    users,
    number,
    appHeading
  });
});
module.exports = router;

and My app.js is:

const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const bodyParser = require('body-parser');

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

const app = express();

/*const logging = function(req, res, next){
  console.log('Logging....')
  next();
}
*/
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
//Body Parser middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended : false}));
//app.use(express.json());
//app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
//app.use(logging);
app.use('/', indexRouter);
app.use('/users', usersRouter);

// 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');
});


app.listen(port=3000 , function(){
  console.log('Server started on port '+ port);
})
module.exports = app;

Solution

  • It seems that it was a typo after all:

    extends layout
    block content
      h1= title
      p Welcome to #{appHeading}
      div
        ul
          for user, i in users
            li= user.name +" - "+ user.id
          li=number
    

    This will work. What happened was that you were accessing users (an array) and not user (the iterated object). I've tried the code in my machine and works just fine.