Problem with findById to display product detail via their Id

I am new to nodeJs and wanted to practice creating a shopping cart. I all succeeded alone but managed to display the detail of products clicked by the user that it does not work: SUMMARY OF MY CODE

I created in my models folder two js files called user.js and jacket.js which each contain a schema and model separately. In my Controllers folder, I have an index.js file which includes:

const User = require ("../models/users")
const Jacket = require ('../models/jacket')

My question is that I want to access the Id of these two documents at the same time: Here is my code

const getProductId = (req, res, next) =>{
  const id = req.params.id
   Promise.all([User.findById(id).exec(), Veste.findById(id).exec() ])
   .then(([product]) => {
      // Or however your template might look like
      res.render('product-detail', { product} )
    })
    .catch(error =>{
      console.log(error)
    })
    
}

My routes folder:

const express = require ('express')
const router = express.Router ()
const getIndexController = require ('../controllers/index')
router.get ('/product/:id', getIndexController.getProductId)

this only works for user but not for jacket Here is my code in my ejs file:

 <h1> <% = product.name%> </h1> 
<img width = "200px" height = "200px" src = "<% = product.image%>" alt = "<% = 
 product.image%>" /> 
<h1> <% = product.description%> </h1> <h1> <% = product.prix%> </h1> 

with user it works well but for jacket it gives me back:

 TypeError: D:\afrikolor\views\product-detail.ejs:8
    6| </head>

    7| <body>

 >> 8|     <h1><%= product.name %></h1> 

    9|     <img width="200px" height="200px" src="<%= product.image %>"  alt="<%= product.image %>"/>

    10|     <h1><%= product.description %></h1>

    11|     <h1><%= product.prix %></h1>


Cannot read property 'name' of null
    at eval (D:\afrikolor\views\product-detail.ejs:12:34)
    at product-detail (D:\afrikolor\node_modules\ejs\lib\ejs.js:691:17)
    at tryHandleCache (D:\afrikolor\node_modules\ejs\lib\ejs.js:272:36)
    at View.exports.renderFile [as engine] (D:\afrikolor\node_modules\ejs\lib\ejs.js:489:10)
    at View.render (D:\afrikolor\node_modules\express\lib\view.js:135:8)
    at tryRender (D:\afrikolor\node_modules\express\lib\application.js:640:10)
    at Function.render (D:\afrikolor\node_modules\express\lib\application.js:592:3)
    at ServerResponse.render (D:\afrikolor\node_modules\express\lib\response.js:1012:7)
    at D:\afrikolor\controllers\index.js:361:11
    at processTicksAndRejections (internal/process/task_queues.js:94:5)

Remove square bracket surrounding ‘product’ variable. Promise.all returns array implicitly and you make it another array inside an array.

Try like this.

.then((product) =>

thank you for your reply
it seems to work but when I click on a product to see the detail:
the page is completely blank

Because, you are sending data to the html page named product which holds array inside. In the html page you are trying to access the array as if it was an object.

Inside html page,

Either you send data to the html page as object , or you get single item from product array. Such,

Thank you again you are absolutely right but for Jacket it works but for User it gives me this:

TypeError: D: \ afrikolor \ views \ product-detail.ejs: 10
    8 |

    9 |

 >> 10 | <h1> <% = product [1] .name%> </h1>

    11 | <img width = "200px" height = "200px" src = "<% = product [1] .image%>" alt = "<% = product [1] .image%>" />

    12 | <h1> <% = product [1] .description%> </h1>

    13 | <h1> <% = product [1]. price%> </h1>


Cannot read property 'name' of null
    at eval (D: \ afrikolor \ views \ product-detail.ejs: 12: 37)
    at product-detail (D: \ afrikolor \ node_modules \ ejs \ lib \ ejs.js: 691: 17)
    at tryHandleCache (D: \ afrikolor \ node_modules \ ejs \ lib \ ejs.js: 272: 36)
    at View.exports.renderFile [as engine] (D: \ afrikolor \ node_modules \ ejs \ lib \ ejs.js: 489: 10)
    at View.render (D: \ afrikolor \ node_modules \ express \ lib \ view.js: 135: 8)
    at tryRender (D: \ afrikolor \ node_modules \ express \ lib \ application.js: 640: 10)
    at Function.render (D: \ afrikolor \ node_modules \ express \ lib \ application.js: 592: 3)
    at ServerResponse.render (D: \ afrikolor \ node_modules \ express \ lib \ response.js: 1012: 7)
    at D: \ afrikolor \ controllers \ index.js: 362: 11
    at processTicksAndRejections (internal / process / task_queues.js: 94: 5)

Does individual item inside product array include user information ?
If so , I 'm guessing the structure like this…

product : [
 {
  image: ....,
  description...,
  price...
  user: {  name : ..., such info}
},
{
..2nd item
}
]

So you can not directly access name on product[1].
Because its a whole object without name property on it.

product[1].user.name

Could be the right answer.

No, I created two different collections in my models folder, one called User:

 const mongoose = require('mongoose')



const userSchema = new mongoose.Schema({
    name:{
       type: String,
   
    },
    description:{
        type: String,
     },

    picture:{
        type: String
    },
    
    price:{
        type: String,
   
    }
})

const User = new mongoose.model('User', userSchema)

module.exports = User

:grinning: :grinning: :grinning:

The other one called jacket:

 const mongoose = require ('mongoose')

const userSchema = new mongoose.Schema ({
    name: {
       type: String,
   
    },
    description:{
        type: String,
     },

    picture:{
        type: String
    },
    
    price:{
        type: String,
   
    }
})

const Jacket = new mongoose.model ('Jacket', userSchema)

module.exports = Jacket

in fact they are different files that I imported

const User = require ("../models/users")
const Jacket = require ('../models/jacket')

I see… but what is Veste ? You are not supposed to be calling it by model name Jacket ?

 Jacket.findById(id).exec()

if I made a mistake by copying the word in French I corrected it sorry I am French speaking

I see no problem… Well, just try to access data inside User html page as product[0] and Jacket is the same as product[1].

If it sucks for product [0] .name

But the problem when I go to the jacket page and click on a product it gives me:

TypeError: D: \ afrikolor \ views \ product-detail.ejs: 10
    8 |

    9 |

 >> 10 | <h1> <% = product [0] .name%> </h1>

    11 | <img width = "200px" height = "200px" src = "<% = product [0] .image%>" alt = "<% = product [0] .image%>" />

    12 | <h1> <% = product [0] .description%> </h1>

    13 | <h1> <% = product [0]. price%> </h1>


Cannot read property 'name' of null
    at eval (D: \ afrikolor \ views \ product-detail.ejs: 12: 37)
    at product-detail (D: \ afrikolor \ node_modules \ ejs \ lib \ ejs.js: 691: 17)
    at tryHandleCache (D: \ afrikolor \ node_modules \ ejs \ lib \ ejs.js: 272: 36)
    at View.exports.renderFile [as engine] (D: \ afrikolor \ node_modules \ ejs \ lib \ ejs.js: 489: 10)
    at View.render (D: \ afrikolor \ node_modules \ express \ lib \ view.js: 135: 8)
    at tryRender (D: \ afrikolor \ node_modules \ express \ lib \ application.js: 640: 10)
    at Function.render (D: \ afrikolor \ node_modules \ express \ lib \ application.js: 592: 3)
    at ServerResponse.render (D: \ afrikolor \ node_modules \ express \ lib \ response.js: 1012: 7)
    at D: \ afrikolor \ controllers \ index.js: 362: 11
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal / process / task_queues.js: 94: 5)

Couldn't we combine the two
example:
<h1> <% = product [0] [1] .name%> </h1>

because jacket and user they have their own page and I try by their Id to display the product detail on one page

You use this syntax for multidimensional array, which you don’t
want to use it here.

Did you use product[0] for user details, and product[1] for jacket details, and still not works ? Make sure you have Jacket and User data coming from database.


sorry but I understood the code correctly:

 product [0] for user details, and product [1] for jacket details

where will he be

To make everything clear just change this block of code to…

…this.

const getProductId = async (req, res, next) =>{
   const id = req.params.id
   try {
     const user =  await User.findById(id);
	 const jacket = await Jacket.findById(id);
   
    res.render('product-detail', { user, jacket } )
	   
   }catch(error =>{
      console.log(error)
   }) 
}

If both user and jacket variable not null, which means you collect data from database without problem. Then, inside product-detail html use user variable for accesing its properties, jacket for its properties.


frankly I'm sorry to tire you

But I believe the problem is in the html part
because we use two different files

Now my question is what we could do in the HTML part to associate {user, jacket}
in 'product-detail'
 <% if(user)  {%>
        <h1><%= user.name %></h1> 
        <img width="200px" height="200px" src="<%= user.image %>"  alt="<%= user.image %>"/>
        <h1><%= user.description %></h1>
        <h1><%= user.prix %></h1>
    <%} else if(jacket)  {%>

        <h1><%= jacket.name %></h1> 
        <img width="200px" height="200px" src="<%= jacket.image %>"  alt="<%= jacket.image %>"/>
        <h1><%= jacket.description %></h1>
        <h1><%= jacket.prix %></h1>
 
   <%} %>

I succeeded by doing

1 Like

No problem at all.

Well, I don’t know how you structure product-detail html page, but simply
you can use same html elements for the both sources. Such,

1 Like

Honestly I don’t know how to thank you all day you helped me a big thank you you are a good developer

if you do tutorials please share me especially with nodejs

I’m glad you solved the problem. Don’t mention about it , we all here to help eachother.
If you stuck you know where to find us :slight_smile:

1 Like