node.jsexpressmongoosehandlebars.jshbs

Handlebar template engine looping issue


I want to print logged users id,name,email from backend using hbs I am using MongoDB but the values are not printing but loop is working.

<h1 class="display-1 text-center text-danger">WELCOME ADMIN</h1>

<table class="table">
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">ID</th>
      <th scope="col">NAME</th>
      <th scope="col">EMAIL</th>
    </tr>
  </thead>
  <tbody>
    {{#each userArray}}
        <tr>
            <td>{{@key}}</td>
            <td>{{this._id}}</td>
            <td>{{this.name}}</td>
            <td>{{this.email}}</td>
        </tr>
        <script>
        
        var namee = {{this.name}}
        if (namee) {
        console.log("Name:", namee);
        }
    
        </script>
    {{/each}}
  </tbody>
</table> 

router:

var express = require('express');
var router = express.Router();
const userReg= require("../models/data")

router.get('/', async(req, res)=> {
 try{
  const userRegList = await userReg.find({});
  console.log("user count :"+userRegList.length);
  res.render('admin',{userArray:userRegList});
  console.log(userRegList)
 }catch(err){
  console.log(err);
 }
  });

  module.exports = router;

model :

const mongoose = require("mongoose");

const personSchema=mongoose.Schema({
    name:String,
    email:String,
    password:String,
    repassword:String,
    birthday:Date,
    phonenumber:String,
    address:String 
});
var Person = mongoose.model("person",personSchema);
module.exports = Person//PersonalData

The data is printing properly in the console, eg. when using console.log(userRegList) but it's not showing when I use {{#each userArray.[0]}} in the template file. It shows the first userdata without fail, but then why does the complete value not print? Help me with this!!


Solution

  • This happens because, by default, in Handlebars >= v4.6.0 accessing prototype properties and methods of the context object is forbidden by the runtime. Handlebars will still loop through the array but it will be blocked from accessing the property values.

    You can override this setting and you can read more here, but it's there to protect your system from malicious actors trying to exploit security vulnerabilities so I would advise you not to override it.

    As mentioned by user @76484 mongoose has a simple lean() method you can chain to any of your queries that you may need to pass to your handlebars views. This returns POJO as opposed to instances of the Mongoose Document Class and can therefore be used in your Handlebars views without encountering this issue.

    By default, Mongoose queries return an instance of the Mongoose Document class. Documents are much heavier than vanilla JavaScript objects, because they have a lot of internal state for change tracking. Enabling the lean option tells Mongoose to skip instantiating a full Mongoose document and just give you the POJO.

    Try this instead:

    const userRegList = await userReg.find({}).lean();
    

    Coincidentally, using lean() will have the added benefit of speeding up your application because:

    Under the hood, after executing a query, Mongoose converts the query results from POJOs to Mongoose documents. If you turn on the lean option, Mongoose skips this step.