Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jade - Loading templates from different directories

I'm trying to work on Peepcode's Node.js Full Stack videos and it seems they're using an older version of express/jade. No mention of using block/extends to render layouts.

The setup used in the app is to have a /views/layout.jade file that loads for all sub-apps. The sub-apps' views are located in /apps//views.

My server.js seems pretty standard. Express is version 3.0.0rc1

require('coffee-script');

var express = require('express')
  , http = require('http')
  , path = require('path');

var app = express();

app.configure(function(){
  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')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

require('./apps/authentication/routes')(app)

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

My routes file for the sub-app is in /apps/authentication/routes

routes.coffee

routes = (app) ->

  app.get "/login", (req,res) ->
    res.render "#{__dirname}/views/login",
      title: "Login"
      stylesheet: 'login'

module.exports = routes

The view I intend on rendering for this.

login.jade

extends layout

block content
  form(action='/sessions', method='post')
    label
      | Username
      input(type='text', name='user')
    label
      | Password 
      input(type='password', name='password)
    input(type='submit', name='Submit')

And Finally the layout.

doctype 5
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/#{stylesheet}.css')
  body
    block content

Going to localhost:3000/login renders this:

Express 500 Error: /Users/StevenNunez/code/HotPie/apps/authentication/views/login.jade:1 > 1| extends layout 2| 3| block content 4| form(action='/sessions', method='post') ENOENT, no such file or directory '/Users/StevenNunez/code/HotPie/apps/authentication/views/layout.jade'

My folder structure:

.
├── '
├── apps
│   └── authentication
│       ├── routes.coffee
│       └── views
│           └── login.jade
├── package.json
├── public
├── server.js
└── views
    ├── index.jade
    └── layout.jade

Thank you for your time.

like image 376
StevenNunez Avatar asked Jul 26 '12 18:07

StevenNunez


3 Answers

It looks like I had to just give the relative path in the extends call.

extends ../../../views/layout

block content
  form(action='/sessions', method='post')
    label
      | Username
      input(type='text', name='user')
    label
      | Password
      input(type='password', name='password')
    input(type='submit', name='Submit')

I didn't have to set app.set('view options',{layout:false});

like image 141
StevenNunez Avatar answered Nov 09 '22 22:11

StevenNunez


You can use variable __dirname to connect views from other directories.

Example:

app.get('/otherurl/' , (req, res) => { 
  res.render(`${__dirname}/../other_project/views/index`) 
});
like image 6
IvanM Avatar answered Nov 09 '22 20:11

IvanM


You are trying to use two methods of rendering... The first layout that extends the layout and the second is block content. When using a layout you are extending automatically the layout file in the folder of login.jade.

It isn't necessary to use extends and you can't use block sentence, but if you want to use extends you have to disable layout.

Add this to the app:

app.set('view options',{layout:false});

after

app.set('view engine', 'jade');

and extend the files like layout extends:

layout.jade

doctype 5
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/#{stylesheet}.css')
  body
    block content

login.jade

extends layout

block content
  form(action='/sessions', method='post')
    label
      | Username
      input(type='text', name='user')
    label
      | Password 
      input(type='password', name='password)
    input(type='submit', name='Submit')

The login file has to be in the same dir. If you want to call other layout you can use the dir like this:

appDirectory
  views
    layout
  otherViews
    login

login.jade

extends ../views/layout    
block content
  form(action='/sessions', method='post')
    label
      | Username
      input(type='text', name='user')
    label
      | Password 
      input(type='password', name='password)
    input(type='submit', name='Submit')
like image 2
andrescabana86 Avatar answered Nov 09 '22 22:11

andrescabana86