user3411989
user3411989

Reputation: 33

Array not being passed to EJS

I am working on a nodejs project with MongoDB for database storage and EJS for templating.

I've encountered a problem where an array of objects is not being correctly passed to EJS. The code works as expected in forums.js (and outputs as expected from console.log) but does not work correctly in forums.ejs. Upon loading the project, I am given an error: "Can not read property forEach of undefined".

Can anyone help me out here? Thank you!

forums.js

var allCategories = await dbo.getForumCategories();
    
allCategories.forEach(async function(category) {    
    category.forumArray = await dbo.getForums({categoryId: new ObjectID(category._id)}); 
    console.log(category.forumArray); //works fine, displays as intended
});
    
res.render('forums.ejs', { categories: allCategories,  user: req.user });

forums.ejs

<% categories.forEach(function(category) { %>
//this part works
//some code

<% category.forumArray.forEach(function(forum) { %>
//this is not working
//Can not read property forEach of undefined

<% }); %>
<% }); %>

Upvotes: 0

Views: 608

Answers (3)

user3411989
user3411989

Reputation: 33

I've fixed my code by replacing the for each loop with a for loop as follows:

for (const category of allCategories) {
    category.forumArray = await dbo.getForums({categoryId: new ObjectID(category._id)});
}

Upvotes: 0

Johannes Brunner
Johannes Brunner

Reputation: 68

In your res.render you pass categories as allCategories but I cant see where category from the ejs file is defined.

Upvotes: 0

Pytth
Pytth

Reputation: 4176

It's because your render function is being called before your forEach has finished running.

See the below example:

const foo = [1, 2, 3];

foo.forEach(async function(bar) {
    bar = await mockCall() + bar;
})

console.log(foo) //> [ 1, 2, 3 ]
console.log("Are methods here running?") //> Logs correctly and demonstrates any function here would run before the `foo.forEach` is done running.

function mockCall() {
    return new Promise((res, rej) => {
        setTimeout(() => {
            res('From the promise: ');
        }, 500)
    })
}

Upvotes: 1

Related Questions