Reputation: 81
I've created my first directive in Angular running on the mean.js 0.4-dev stack vertical project file structure which I auto generated with Yeoman.
The directive compiles correctly when I use the 'template:' property however when I try to move the contents to a template file and use the 'templateUrl:' property it loads the un-compiled 'layout.server.view.html' file instead of my 'contact-form.client.template.html' file. It seems like it can't find my template file no matter what I set the path to (I tried all paths up the tree).
Can anyone see what I'm doing wrong. Perhaps someone can explain how angular resolves relative paths.
My program structure is like this... I generated a module for a contact form using the 0.4-dev of the generator-mean. The module contains my directive. My file structure is like this:
/app
/config
/modules
/contact-forms
/client
/config
/controllers
contact-forms.client.controller.js
/views
contact-form.client.template.html <- 2. should load this
contact-forms.client.module.js
/core
/client
/views
home.client.view.html <- 1. <contact-form> directive here
/server
/controllers
/routes
/views
layout.server.view.html <- 3. instead loads this
/node_modules
/public
/uploads
My directive code is this:
contactForms.directive('contactForm',[function(){
return {
restrict: 'E',
transclude: 'true',
//template: '<div>hello world!</div>', <--this works
templateUrl: 'modules/contact-forms/client/views/contact-form.client.template.html'
};
}]);
And my template file is like this:
<div>
<form class="row col-md-6 col-md-offset-3 text-left">
<div class="form-group col-md-12">
<label for="Name">Name</label>
<input type="text" class="form-control" id="inputName">
</div>
<div class="form-group col-md-12">
<label for="email">Email</label>
<input type="email" class="form-control" id="inputEmail">
</div>
<div class="form-group col-xs-12">
<label for="emailSubject">Subject</label>
<input type="text" class="form-control" id="inputSubject">
</div>
<div class="form-group col-xs-12">
<label for="emailMessage">Message</label>
<input type="text" class="form-control" id="inputMessage">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
I've seen a few posts on this type of issue however none of them seem to match my use case. I'm running a local express server so I don't think this post is the issue (Couldn't load template using templateUrl in Angularjs).
This post talks about templateUrl being spelt wrong but I think mine is correct (Angular directive templateURL not being loaded. Why?)
I understand from this post on the angular github (https://github.com/angular/angular.js/issues/10965) that the default behavior of angular.js is to load the index file in the event of not finding a template. The comment from feb 4 suggests this is how it has to be. There is no errors in my browser console so I'm not really sure whats happening.
My node.js routing hasn't been changed from the Yeoman install of the mean.js stack:
module.exports = function(app) {
// Root routing
var core = require('../controllers/core.server.controller');
// Define error pages
app.route('/server-error').get(core.renderServerError);
app.route('/not-found').get(core.renderNotFound);
// Define application route
app.route('/*').get(core.renderIndex);
};
and:
'use strict';
/**
* Render the main application page
*/
exports.renderIndex = function(req, res) {
res.render('modules/core/server/views/index', {
user: req.user || null
});
};
/**
* Render the server error page
*/
exports.renderServerError = function(req, res) {
res.status(500).render('modules/core/server/views/500', {
error: 'Oops! Something went wrong...'
});
};
/**
* Render the server not found page
*/
exports.renderNotFound = function(req, res) {
res.status(404).render('modules/core/server/views/404', {
url: req.originalUrl
});
};
Do i need to add a route for the template?
Upvotes: 4
Views: 1695
Reputation: 81
I figured out why it's not finding the template. In mean.js 0.4.0 the express configuration file has a static routing function which removes the /client from the paths
/**
* Configure the modules static routes
*/
module.exports.initModulesClientRoutes = function (app) {
// Setting the app router and static folder
app.use('/', express.static(path.resolve('./public')));
// Globbing static routing
config.folders.client.forEach(function (staticPath) {
app.use(staticPath.replace('/client', ''), express.static(path.resolve('./' + staticPath)));
});
};
So my line:
templateUrl: 'modules/contact-forms/client/views/contact-form.client.template.html'
should be:
templateUrl: 'modules/contact-forms/views/contact-form.client.template.html'
Which seems to work. No idea why they remove this /client from the path. There is a reference to it on this issue (https://github.com/meanjs/mean/issues/608) however it doesn't seem to mention exactly why they do it.
If you want to remove this behavior from mean.js you can do the following (Warning: The yeoman meanjs:vertical-module generator creates all paths without the client so either don't use it or correct its path output after creating each module.):
Remove the replace() function in express.js so it looks like this:
/**
* Configure the modules static routes
*/
module.exports.initModulesClientRoutes = function (app) {
// Setting the app router and static folder
app.use('/', express.static(path.resolve('./public')));
// Globbing static routing
config.folders.client.forEach(function (staticPath) {
app.use(staticPath, express.static(path.resolve('./' + staticPath)));
});
};
For each module in the project add a /client after the module name in every static path. I did this in a brute force fashion however I'm sure there's a smarter way.
In the config.js file remove the /client masks from lines 121 and 124 so they look like the following:
// Setting Globbed js files
config.files.client.js = getGlobbedPaths(assets.client.lib.js, 'public/').concat(getGlobbedPaths(assets.client.js, 'public/'));
// Setting Globbed css files
config.files.client.css = getGlobbedPaths(assets.client.lib.css, 'public/').concat(getGlobbedPaths(assets.client.css, 'public/'));
Seems to work and doesn't appear to be any issues so far I'll comment if I run into any issues.
Upvotes: 3