Search code examples
node.jsexpressejsknex.js

Pass result of Knex.js select to ejs template


I'm currently working on a project in express and I'm using knex.js for my queries and migrations.

I haven't touched node in a while so I'm a bit rusty. Essentially I'm trying to select records from one of my tables and then call the function in one of my routes to then iterate through and output it in my ejs template.

Unit Model

'use strict'
const knex = require('knex')(require('../../knexfile'))
module.exports = function(app) {

    this.getAll = function() {
        knex.select('id', 'unit_prefix', 'unit_name').from('units').then(function(units) {
            return units;
        })
    }
    return this
}

Then in my routes.js file:

 app.get('/dashboard', ensureAuthenticated, function(req, res) {
        // console.log(req.user)
        console.log(unitModel.getAll)
        res.render('dashboard', { user: req.user, units: unitModel.getAll })
    })

If I console.log the result of unitModel.getAll I get [Function]. I've read about how knex uses promises and is asynchronous however I still haven't managed to use other answers to solve my rather simple issue.

In my dashboard.ejs file I have this code:

<h3>Jump to unit:</h3>
             <%if (units.length > 0) { %>
              <% units.forEach(function(unit) { %>
                <div class="dashboard-course-item" tooltip="First year unit, covers the basics of web foundations">
                  (<%= unit.unit_prefix %>) <%= unit.unit_name %>
                </div>
              <% }) %>
              <% } else { %>
                <strong>Currently no units have been created.</strong>
              <% } %> 

I currently have one record in the units table and always see the Currently no units have been created. message.

What do I need to change to return an array or object that I can iterate over in my ejs template?

Thanks in advance!


Solution

  • Promises return their values asynchronously in their .then callback function, if you return the promise itself it will return undefined since in that moment the promise still hasn't resolved.

    To make your code work you should do something like this:

    Unit Model

    'use strict'
    const knex = require('knex')(require('../../knexfile'))
    module.exports = function(app) {
    
    this.getAll = function(){
       return new Promise(function(resolve,reject) {
        knex.select('id', 'unit_prefix', 'unit_name').from('units')
         .then(function(units) { resolve(units);})
         .catch(function(error) {reject(error);})
     })
    }
    return this
    }
    

    routes.js

    app.get('/dashboard', ensureAuthenticated, function(req, res) {
        // console.log(req.user)
        unitModel.getAll()
          .then(function(units){        
            res.render('dashboard', { 
             user: req.user, 
             units: units
        })
       })
    })