0

I have an array of objects being pulled from Mongo, which looks like this:

[
  {
    _id: 5f2038de019c99595df20977,
    fromDoctor: 'Dummyname1',
    Message: 'dummymessage1'
  },
  {
    _id: 5f2038e5019c99595df20978,
    fromDoctor: 'Dummyname2',
    Message: 'dummymessage2'
  }
]

I'd like to insert this array, which i call allMessages, into an EJS file, displaying them all, something like this:

    <div class="NoticeMessage">
        <p>Posted by ${notice.fromDoctor}</p>
        </br>
        <p>Message</p>
        </br>
        <p>${notice.Message}</p>
    </div>
        ;

I'm attempting to pass the array to ejs when /board (the route) is called, like this:

res.render('Board', {Messages : allMessages});

(I have confirmed that the array is defining properly, allMessages is equal to above array)

I'd like to insert the array and run .forEach with above template code on it, creating a new NoticeMessage for each object in the array, and inserting them into this:

<div class="row mt-5">
    <div class="card card-body">
        <h2>Message board</h2>
        </br>
        </br>
        <!--INSERT HERE-->
    </div>
</div>

But i really don't know how to go about it. Can anyone help me out?

Honeybun
  • 85
  • 1
  • 8

2 Answers2

0

You can use a simple for .. of-loop to render the contents of each message:

<% for(const notice of Messages) {%>
    <div class="NoticeMessage">
        <p>Posted by <%= notice.fromDoctor %></p>
        <p>Message</p>
        <p><%= notice.Message %></p>
    </div>
<% } %>

EDIT:

To handle the asynchronicity just return the promise from the toArray() function, and await this in your controller. After that, do the rendering:

// in your model get rid of the callback and just return the promise
async function loadMessages() {
 return mongoose.connection.db.collection("BulletBoardDB").find().toArray();
}

// in your controller await the promise and do the rendering
renderBoard = async(req, res) => {
    let allMessages  = await this.boardModel.loadMessages();
    console.log(allMessages);
    res.render('Board', {
        Messages: allMessages
    });
};
eol
  • 23,236
  • 5
  • 46
  • 64
  • Seems like this would be the solution, but whenever I run this, It's not loading anything in at all, just seems like there isn't any code. It's not returning any errors either, what could be going wrong? – Honeybun Jul 28 '20 at 15:59
  • Are you using `mongoose` to fetch the data from mongo? – eol Jul 28 '20 at 16:12
  • Well, in a way - I'm fetching it using native mongoDB inside a mongoose connection, like this: ```js async loadMessages() { let allMessages = ""; mongoose.connection.db.collection("BulletBoardDB").find() .toArray((error, result) => { if (error) throw error; console.log(result); allMessages = result; }); } ``` which is returning the array i posted in the original question – Honeybun Jul 28 '20 at 16:15
  • You need to make sure to the rendering inside the callback - updated the answer. The reason for this has been explained countless times on SO :) Check this for example: https://stackoverflow.com/questions/23339907/returning-a-value-from-callback-function-in-node-js – eol Jul 28 '20 at 16:20
  • Ah, I see - Theres only one issue with that, which is that i'm being force to follow strict MVC by tutors for my exam project, so the loadMessages() function is defined as a method of the boardModel, which is being called together with the res.render inside the boardController, as follows: ```js renderBoard = async (req, res) => { let allMessages = ""; this.boardModel.loadMessages(); console.log(allMessages); res.render('Board', {Messages : JSON.parse(allMessages)}); }; ``` Sorry i left this out originally, should've been more specific – Honeybun Jul 28 '20 at 16:25
  • `toArray` already returns a promise - so you can just await this in your controller. I've updated the answer once more. – eol Jul 28 '20 at 16:33
  • There's no way to pass the array from my model.js to the controller.js and run it from there? the issue is definitely that allMessages is undefined, as it's not being passed there :/ – Honeybun Jul 28 '20 at 16:35
  • That's exactly what I'm doing. It is an async operation though - you need to await it. Once it's finished the returned promise will resolve to the array of data! – eol Jul 28 '20 at 16:37
  • Its returning now, the console is logging succesfully! I'm being returned an error in the browser now that "Messages is not iterable", what could be causing this? – Honeybun Jul 28 '20 at 16:39
  • Have you tried not using `JSON.parse(allMessages)`? Try it like I did in my answer. – eol Jul 28 '20 at 17:03
  • ```js renderBoard = async (req, res) => { let allMessages = await this.boardModel.loadMessages(); console.log(allMessages); res.render('Board', {Messages: allMessages}); };``` Yea, still just returning that it isn't iterable :/ – Honeybun Jul 28 '20 at 17:33
0

Does the following help you?
The render function:

res.render('Board', {Messages : JSON.parse(allMessages)});

For your ejs file:

<div class="row mt-5">
<div class="card card-body">
    <h2>Message board</h2>
    </br>
    </br>
    <% Messages.forEach(function(message){ %>
    <div class="NoticeMessage">
      <p>Posted by <%= message.fromDoctor %></p>
    </br>
    <p>Message</p>
    </br>
    <p><%= message.Message %></p>
</div>
 <% }) %>
</div>
  • This results in the page just loading indefinitely, no clue what kind of error is happening as nothing is logging, and it's not returning anything in the browser :/ – Honeybun Jul 28 '20 at 16:08