user2538720
user2538720

Reputation: 191

how do i fix routes to find views inside subfolders in node.js

i am trying to create a route for localhost:port/admin/ and i want to keep the routes.js files and view.js files in matching folders so i wont have too much spaggeti later on

but i keep getting: 500 Error: Failed to lookup view "/admin/manage_subjects" for trying to create a new route and using same folders few the same

i have the following view folder with express

mainapp(root)
  routes(folder)
    admin(folder)
      index.js(nested inside admin)
    index.js(nested inside routes)
  views(folder)
    admin(folder)
      admin_layout.jade(nested inside admin)
      manage_subjects.jade(nested inside admin)
    index.jade(nested inside views)
    layout.jade(nested inside views)

code: routes/admin/index.js

exports.index = function (req, res) {
res.render('manage_subjects',{title:'Express'});}

views/admin/manage_subjects.jade

extends admin_layout
block content
h1 = title
p Welcome to #{title}

my app.js code

/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , admin_routes = require('./routes/admin/')
  , user = require('./routes/user')
  , http = require('http')
  , path = require('path')
  , repository = new (require('./domain_model/repository'))();

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());
}

//fill local subjects
repository.subjects.GetAll(function (err, data) {
    if (err) throw err;
    app.locals.subjects = data;
});

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

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

Upvotes: 15

Views: 18379

Answers (4)

Uche Ozoemena
Uche Ozoemena

Reputation: 926

I had a similar problem and what worked for me was setting the views folder in both the main app file and in the router file too.

So in the main app.js file I had:

app.set('views', viewsFolderPath);

And inside my router.js file I also did the same thing:

app.set('views', viewsFolderPath);

Upvotes: 0

Bikky Kumar
Bikky Kumar

Reputation: 21

Simple Answer for sub-folders inside the views folder (mine is called frontend)

click here the picture to see the folder structure

file app.js


app.set('views', [path.join(__dirname, 'frontend'), path.join(__dirname, 'frontend/locked'), path.join(__dirname, 'frontend/template'), path.join(__dirname, 'frontend/public')]);
app.set('view engine', 'pug')

Upvotes: 1

Hardy
Hardy

Reputation: 477

I've been dealing with what I think is the same problem and figured out how to fix it. So in case someone else comes across this problem I'm posting my solution.

So here is what I had that was causing 404's and 500's

app.js

var routes = require('./routes/index');
var admin = require('./routes/admin');

app.use('/', routes);
app.use('/admin', admin);

and here was my routes/index.js

//append routes
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
    res.render('index', {title: 'Express'});
});

module.exports = router;

and my routes/admin.js:

var express = require('express');
var router = express.Router();

router.get('/admin', function(req, res) {
    res.render('admin/index', {title: 'Express'});
});

module.exports = router;

by defining the second /admin inside the router.get() function I think I was effectively telling node to look for the html in my views folder under the following path views/admin/admin/index.ejs. So to fix that all I had to do was remove either the /admin from the router.get() or the /admin from the app.use() So my working code now looks like this:

app.js

var routes = require('./routes/index');
var admin = require('./routes/admin');

app.use('/', routes);
app.use('/admin', admin); //I left the /admin here and instead removed the one in routes/admin.js

and here was my routes/index.js

//append routes
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
    res.render('index', {title: 'Express'});
});

module.exports = router;

and my routes/admin.js:

var express = require('express');
var router = express.Router();

router.get('/', function(req, res) { //NOTICE THE CHANGE HERE
    res.render('admin/index', {title: 'Express'});
});

module.exports = router;

So making that change made it so I could have sub folders in my views folder.

Upvotes: 15

David
David

Reputation: 317

I'd check out TJ's video on Modular apps on his vimeo the best part about this work flow is your code becomes really flexible and it's alot easier to stay DRY.

Additionally I would do something like this with my app.set("views")

var path = require("path");
app.set('views', path.join(__dirname, 'views'));

// you can then extend this to the example for routes

Another alternative would be something like in your app.js file:

var express require("express")
var app = express()
var routes = require("./path/to/routes")(app)

and then routes would look like:

routes = function (app) {
  app.get("/route", middleWareifYou.gotIt, route.handler || function (req, res) {
    res.send("some msg");
  });
};

module.exports = routes

Cheers, I hope this helps!

Upvotes: 0

Related Questions