Search code examples
node.jsejsknex.js

Display data from different queries from Knex in EJS page


var getTimer = function(owner, callback){
    if(owner !== undefined) {
        knex.table('timer').where({id_owner : owner.id_user}).select().orderBy('created','asc').then(function(result) {
            callback(result);
        });
    }
}

var getTags = function(timer, callback) {
    if(timer !== undefined) {
        knex.table('timer_tag').innerJoin('tags', 'id_tg', 'tags.id_tag').where({id_tmr : timer.id_timer}).select('tags.nome_tag').orderBy('tags.nome_tag', 'desc').then(function(result) {
            callback(result);
        });
    }
}

var index = function(req, res, next) {
    if(!req.isAuthenticated()){
        return res.redirect('/login');
    }
    else {   
        var user = req.user;
        //here I render the EJS page
        getTimer(user, function(results) {
            return res.render('index.ejs', {title: "'s Home", user: user, data: results});
        })
        //------------------
    }
};

I'm having an issue getting data from a db because I need to retrieve them from multiple tables, but show them on the same page

In the EJS page I use a for loop cycling all the timers, but I don't know how to display tags too


Solution

  • I haven't used Knex.js myself but based on the code you've posted I think I can give this a go.

    Given you need to make many requests and wait for the results the simplest approach is to use promises. You already have promises but you've converted them to callbacks.

    var getTimer = function(owner) {
        return knex
            .table('timer')
            .where({id_owner: owner.id_user})
            .select()
            .orderBy('created','asc');
    }
    
    var getTags = function(timer) {
        return knex
            .table('timer_tag')
            .innerJoin('tags', 'id_tg', 'tags.id_tag')
            .where({id_tmr: timer.id_timer})
            .select('tags.nome_tag')
            .orderBy('tags.nome_tag', 'desc');
    }
    

    Notice that I'm returning the promises created by Knex and the callbacks are gone entirely. Strictly speaking the return values here are query builders and not promises but they support the promises interface so that's close enough.

    Now for the route:

    var index = function(req, res, next) {
        if(!req.isAuthenticated()){
            return res.redirect('/login');
        }
        else {   
            var user = req.user;
    
            getTimer(user).then(function(timers) {
                // I'm assuming that 'timers' is an array of objects
                // in the same form expected by getTags
                var promises = timers.map(getTags);
    
                Promises.all(promises).then(function(tags) {
                    res.render('index.ejs', {
                        title: "'s Home",
                        user: user,
                        timers: timers,
                        tags: tags
                    });
                });
            });
        }
    };
    

    I haven't made any attempt to pair up the tags with their corresponding timers but they should have the same index within their respective arrays so you can either do some pre-processing in the router to get the data in your desired format, or you can just pair them up by index in your EJS template.

    You'll need to use .catch to handle the error cases.