Otoris
Otoris

Reputation: 307

How to use NodeJS + ExpressJS to pass an array to Jade for display?

I come from a very "functional" style of programming (PHP, Lua, C) and I'm trying to transition my thinking to the MVC model NodeJS uses. Currently, this is a very steep learning curve for me.

I've been banging my head against the wall trying to get a simple MySQL array to print out to Jade.

app.js

/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , http = require('http')
  , path = require('path')
  , mysql = require('mysql');

var app = express();


// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

app.get('/', routes.index);
app.get('/users', user.list);

//MySQL
var sqlInfo = {
  host: '12.34.56.78', 
  user: 'user',
  password: 'pass', 
  database: 'user'
}

var client = mysql.createConnection(sqlInfo);
client.connect();

client.query( "SELECT * FROM list ORDER BY status ASC LIMIT 25", function(err, row, fields){
  if (err) throw err;
  else {
    var applications = row;
    app.render("applications", applications, function(err, html){});
  }  
});

client.end();

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

index.jade

extends layout

block content
  div.container
    div.content   
      - if (typeof(applications) !== 'undefined')
        ul
          - each app in data
            li= app.status
      - else
        p Blank slate mate...

  div.footer

I think my issue is stemming from the app.render/res.render function... The concept of this function is not really clicking and I'm having problems getting it to work like I've seen in so many other MySQL + NodeJS examples.

Any tips or hints are much appreciated!

Upvotes: 3

Views: 7627

Answers (3)

robertklep
robertklep

Reputation: 203359

The problem is that you're trying to render a query outside the HTTP flow. That could be your intention (in which case I'm interested in hearing what exactly you're trying to do with the rendered result), but usually, you wait for an HTTP request before you return the results of your query.

For example:

app.get('/test', function(req, res) {
  // connect to MySQL server
  var client = mysql.createConnection(sqlInfo);
  client.connect();

  // Perform query and wait for results
  client.query( "SELECT * FROM list ORDER BY status ASC LIMIT 25", function(err, row, fields) {
    // Done with the connection
    client.end();

    // Handle error
    if (err) throw err;
    else {
      // We got a result: render it
      var applications = row;
      res.render("applications", { applications : applications });
    }
  });
});

A few pointers:

  • You can look at the results by opening http://localhost:PORT/test
  • Take a look at connection pooling for MySQL, which maintains a pool of connections to the MySQL server instead of having to create a new connection each time you handle a request;
  • In your example code, you were sending client.end() right after client.query(), but without waiting for the query to return any results. So I moved client.end() to inside the code which handles the query result, to make sure the connection is ended only after the results are returned;
  • in your template, you reference a variable called data, but I think that should be applications;

Upvotes: 5

Will Klein
Will Klein

Reputation: 2294

I can see two issues here.

First, you pass"applications" as the first parameter to app.render(). This should probably be "index" to match your view name.

Second, and this is the key point I think you're missing, is that you need to do something with html in the function you pass to app.render().

app.render("applications", applications, function(err, html){
    //see what you have for html here
});

The idea behind passing a function in to render is it works like a callback. You can inspect err to see if there was a problem with rendering the view. If there was no error, html should have the rendered HTML based on the Jade template and whatever data you passed in (applications).

If you still have a problem, I have a couple suggestions. You should probably debug your data to see what that looks like. Make sure the MySQL query returns data in a format your expecting. Then you can see if your template works. Try passing in a simple data object and use a simple Jade template at first to make sure you're calling app.render() correctly.

I hope that helps!

Upvotes: 1

user568109
user568109

Reputation: 48003

You can pass variables to the jade when rendering view like this:

res.render('index', { applications: applications }, function(err, html){});

Then you can use it inside your index.jade:

if (typeof(applications) !== 'undefined')

Upvotes: 1

Related Questions