I'm using express 4 to render jade templates for angular. When I try and route with a dynamic parameter on the client, my routes don't match so express sends layout.jade
twice.
app.config(function($stateProvider, $urlRouterProvider, $locationProvider){
$stateProvider
.state('home', {
url: '/',
templateUrl: 'views/home',
controller: 'MainCtrl'
})
.state('about', {
// works fine
url: '/about',
templateUrl: 'views/about'
})
.state('post', {
url: '/post/{id}',
// view does not render
templateUrl: 'views/post',
controller: 'PostCtrl'
});
$urlRouterProvider.otherwise('/');
$locationProvider.html5Mode(true);
})
For when I hit http://localhost:3000/post/0
the request goes out to Request URL:http://localhost:3000/post/views/post
which does not match anything.
I want to render public/views/post.jade
when hitting /post/{id}
These is the express 4 routes and config:
app.set('views', path.join(config.rootPath, '/views'));
app.set('view engine', 'jade')
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(config.rootPath, 'public')));
app.get('/views/:name', function(req, res){
res.render('../public/views/' + req.params.name);
})
app.get('*', function(req, res){
res.render('layout');
});
Note If I change the post state to use template:
.state('post', {
url: '/post/{id}',
template: '<div>{{ post }}</div> is that',
controller: 'PostCtrl'
});
The template will render fine. The problem is when I use templateUrl: 'views/post'
Update:
From the home view I can navigate to see post.jade
with:
div(ng-repeat='post in posts track by $index')
a(ui-sref='post({ id:{{ $index }} })') Comments
That navigates to views/post
alright, but if I refresh the page I get the same layout-layout error
(I'm assuming config.rootPath
is the root directory of your project. You should check out http://nodejs.org/docs/latest/api/globals.html#globals_dirname)
So first of all, if you have all of your views in a directory {config.rootPath}/public/views
, this line:
app.set('views', path.join(config.rootPath, '/views'));
is basically telling Express to look for your jade files in {config.rootPath}/views
, which isn't the correct location. Try:
app.set('views', path.join(config.rootPath, 'public', 'views'));
This will allow you to just specify paths relative to public/views
whenever you want to render a jade file - so on the angular side of things, if you wanted to render public/views/post.jade
when hitting /post/{id}
, it would just be:
.state('post', {
url: '/post/{id}',
templateUrl: '/post',
controller: 'PostCtrl'
})
and on the backend, loading the views would just look like
app.get('/:name', function(req, res){
res.render(req.params.name);
})
(Note: It's not the best idea to have a param as the base of the path. You'd want to have a directory public/views/partials
for your partials, so instead of '/:name'
- which would intercept pretty much everything - you'd use '/partials/:name'
)