Closed sheniff closed 11 years ago
Definitely interested in providing access to templates that way. @techpines Any ideas on how we might do this with Asset Rack?
In the mean time, if you drop your templates in the views/templates
directory, they'll be automatically injected into a hidden div in your layout file and you can grab them via selectors.
Yeah, that's right. However, AngularJS relies on XHR requests to retrieve partials directly from the server. I'll use Backbone in the mean time as I can use this kind of approach with it or I'll look for the way to get the templates from the main template with angular.
Thanks!
@techpines might make sense to include a TemplateController
in new projects with an index
action which just spits out the appropriate template from memory and serves it with the appropriate MIME type.
@sheniff can you give us an example request that angular might send for a template? i.e. does the :name
look like tabbar
or tabbar.ejs
?
Sure. This is an example of route provider in AngularJS, the common place to locate partials calls:
$routeProvider.when('/welcome', {
templateUrl : 'templates/welcome.html',
controller : WelcomeController
});
It usually comes with the file extension as partials are usually expected to be regular HTML files, just with the frontend (angular) logic in them, but plain HTML in the end.
@garth wrote an AngularTemplates asset for AssetRack:
https://github.com/techpines/asset-rack/tree/master/lib#angulartemplatesasset
Would that work for you?
@techpines Would that work inside of Sails presently?
It can be run as express middleware like this:
var rack = require('asset-rack');
app.use(new rack.AngularTemplatesAsset({
url: '/templates.js'
dirname: __dirname + '/templates'
}));
So I believe if my sails knowledge is up to date, that he could run it through a policy.
But if you wanted to add it to the assets being managed by sails in assets.js
that would be a different story. Just depends how you wanted to do that piece. Maybe a TemplateController
would be a good route to go?
Hmmm... Maybe using asset stack could do the trick. But I'm definitely more into the TemplateController solution, as it seems cleaner to use and understand :)
I'll try both though and I'll let you know how they were!
Thanks! On Mar 6, 2013 5:00 PM, "Brad Carleton" notifications@github.com wrote:
It can be run as express middleware like this:
var rack = require('asset-rack');app.use(new rack.AngularTemplatesAsset({ url: '/templates.js' dirname: __dirname + '/templates'}));
So I believe if my sails knowledge is up to date, that he could run it through a policy.
But if you wanted to add it to the assets being managed by sails in assets.js that would be a different story. Just depends how you wanted to do that piece. Maybe a TemplateController would be a good route to go?
— Reply to this email directly or view it on GitHubhttps://github.com/balderdashy/sails/issues/205#issuecomment-14536816 .
@sheniff Looking forward to it :+1:
I'm using this workaround right now (based on angular-express-seed conventions):
angular.module('app', [])
.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.when('/index', {
template: $('#template-index').html(),
controller: IndexCtrl
});
});
And dumping everything in /templates as such:
<script id="template-index" type="template/html">
{{angular stuff}}
</script>
works fine, but makes the page a bit heavy
@Tidwell would a TemplatesController be preferable here? Happy to investigate that approach. We could look at a convention where templates can be separated by subdirectories and served conditionally to different areas of your app-- something like:
GET /templates
(get all top-level templates in /assets/templates)
GET /templates/settings
(get all templates in /assets/templates/settings)
GET /templates/settings/account
(get all templates in /assets/templates/settings/account)
I think we'd still want to provide the option of using the <%- assets.templateLibrary() %> partial, but the REST call to grab templates would be another alternative.
Doing it this way means you could grab only the templates you need, and even control access to them if you're in a high-security situation. Of course, templates are usually safe, but I could see some scenarios where it would matter.
Implementation in pseudo-code:
// api/controllers/TemplateController.js
module.exports = {
index: function (req,res) {
var listOfAssetSourcePaths = sails.config.assets.sequence;
var htmlString = "";
async.each(listOfAssetSourcePaths, function (path,cb) {
require('fs').readFile(path,function (err, contents) {
if (err) return cb(err);
htmlString += contents;
});
}, function (err) {
if (err) return res.send(err,500);
res.contentType('text/html');
res.send(htmlString);
});
}
};
We could also use streams in the above example to provide better performance, sending the templates directly from disk straight down chunkwise in the response.
Closing in favor of https://github.com/balderdashy/sails/issues/273
But we definitely need some solid AngularJS examples!
I have been playing around with SailsJS for a new project lately and put together this simple CRUD demo using Sails and Mongo as the backend layer and Angular Resource as the REST connector to Sails. It also includes an Angular JS front-end with some Socket.io interaction and some other goodies.
I am really impressed with Sails and it's definitely been fun to play with so far. I thought this might also be useful for others since there aren't a ton of examples out there.
Thanks for the awesome framework!
@levid I have noticed that your https://github.com/levid/angular-sails-socketio-mongo-demo example based on Sails 0.8, Is it the same for 0.9 ? Note, I just started with Sails.
No, many things have changed. Check out the Migration Guide
For everyone who is interested in using Sails with Angular, i've written a little ngModule for sails socket.io API: https://github.com/kyjan/angular-sails
Best regards :)
@kyjan - I can't wait to check out your module! Thanks for your contribution. :+1:
i would like to use mongoose/angular
I grabbed the module @kyjan posted a few months back. When I include the ngModule into my project, I am getting a reference error telling me "io is not defined". Am I missing the socket.io dependency or maybe not installing it correctly in my project? Thanks for the help.
@jchiellini you have to include the socket.io.js file before. The ngSails-Module is just a wrapper to make the socket messages available to angular's scope.
So what's the convention filestructure for a sails-angular application?
I prefer to separate the angular files by feature and end up getting something like: assets/angularjs/[feature]/controllers/ assets/angularjs/[feature]/services/ assets/angularjs/[feature]/directives/ assets/angularjs/[feature]/views/
The idea is separate packages in features to allow export as bower_components
+1 for @albertosouza's solution. Thanks!
**Quick note to clarify the way AngularJS handles templates***
I know nothing about Sails, but this came up in a search and I've been working w/ AngularJS for a couple of years so I thought I could at least clarify that end of things a bit.
You don't want to XHR every partial. All component directives have a template and many of them use templateUrl
(it's cleaner), along w/ angular-ui-router $states
and of course plain 'ol ngView
.
How it actually works
Assuming the definition object for whatever requires a template does not have the template
property inlined, we inevitably get to something like this in AngularJS:
var template = $http.get(templateUrl, { cache: $templateCache });
The { cache: $templateCache }
is critical because angular is always trying to not make this request if it can help it. What this actually does is makes sure all templates return the same promise (whether cached or not... always a good practice), and that if we do have to make the request, it gets cached for duration of the app life cycle.
Here's a boiled down version what happens in $http
:
var template;
// See if cache was provided, and if so
if (config.cache) {
// In this case: $templateCache.get('my-partial.tpl.html');
cachedResponse = config.cache.get(config.url);
if (cachedResponse) {
// Resolve `$http` promise w/ response from `$templateCache` in this case
resolvePromise(cachedResponse);
}
}
But the most important thing here is that you don't really want to load (templates) from XHR unless it makes sense. So how do we get these into the cache so they are available when we need them? Angular has two core features for exactly this purpose:
The script directive. This is dead simple:
{
compile: function(element, attr) {
if (attr.type == 'text/ng-template') {
var templateUrl = attr.id, text = element[0].text;
$templateCache.put(templateUrl, text);
}
}
}
It literally just checks for the "text\ng-template"
type and adds the contents to $templateCache
if found. Otherwise it leaves it alone.
Thus...
<script type="text/ng-template" id="my-partial.tpl.html"><foo>Template</foo></script>
The second is to just access $templateCache
directly in a config
block before the app runs:
angular.module('cornflakes').config([
'$templateCache', function($templateCache) {
$templateCache.put('foo.tpl.html', '<bar>Some HTML I already have somehow.</bar>');
};
])
This is extremely useful, since it allows you to preload all the templates you want to for each module. How? Simple:
Sooo...
When working w/ small apps, it's probably best to just let html2js or something similar just build all your templates and include the full payload. Your application script is downloaded, cached and you never have to think about it.
With large apps, you'll end up probably doing one or more of:
Basically, in a big app, you're going to have to deal w/ this in a much more serious way.
So the only question left is medium complexity apps. Your mileage will vary, obviously, but some combination of XHR views decorated on the server side and pre-built static templates is probably going to be sufficient for most scenarios.
* Clearly I was lying about "quick", sorry
Cheers
Edit: I can't wait to check out Sails. It looks amazing :+1: Edit2: Fixed sleep-deprivation-induced mistakes
+1 for @albertosouza's solution. Its simple and elegant way to serve Angular HTML templates from SailsJS backend.
Hi, I'd like to use AngularJS for the frontend in my sails app.
The only problem is that I need to access to the templates (same ones that now are under /assets/js/templates) directly using an URL, commonly
I know that can be done with express, just by adding
in the routes section in app.js
But when I try to do something similar in Sails, in routes.js, it says routes is not defined.
Any idea how can I define an url that way? to directly access to some resources?