Using Express Handlebars and Angular JS - javascript

Background
I am currently building a website that uses NodeJS for the server, Express Handlebars(Just Handlebars but server side) , and hopefully AngularJS for some client side stuff.
The Problem
AngularJS and Handlebars use the same syntax for templating
{{foo}}
This causes a problem where AngularJS code will be interpreted by Express Handlebars first, which will then throw an error because the data it is trying to pull only exists in Angular not Node.
The Question
Is there a way to get AngularJS and Express Handlebars to work together?
Possible Solutions
Change the syntax of AngularJS
I was looking at BackboneJS and it looks like it is possible to change the syntax. There could possibly be something similar is AngularJS.
Create a ng helper in Express Handlebars.
It would just return its un-parsed content. However I couldn't figure out how to do this.

Your first solution is possible, AngularJS allow to change the start/end symbols of text interpolation like this:
appModule.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
Then you could use it in your template:
<div>{[{message}]}</div>
Also see: $interpolateProvider documentation
Hope this helps.

You can always use the ng-bind syntax instead:
<p ng-bind="user.profile.description"></p>
This is identical to
<p>{{user.profile.description}}</p>
From the Angular docs for ngBind:
Typically, you don't use ngBind directly, but instead you use the double curly markup like {{ expression }} which is similar but less verbose.
It is preferable to use ngBind instead of {{ expression }} if a template is momentarily displayed by the browser in its raw state before Angular compiles it. Since ngBind is an element attribute, it makes the bindings invisible to the user while the page is loading.

In order to maintain the AngularJS Style, your second solution is better, Create a helper in Express Handlebars.
References to the Handlebars Web Site: http://handlebarsjs.com/block_helpers.html, you can register a helper raw-helper
Handlebars.registerHelper('raw-helper', function(options) {
return options.fn();
});
and use it in your hbs template by putting it in a quadruple-stash {{{{
{{{{raw-helper}}}}
<div class="container" ng-controller="AppCtrl">
Total Members: {{members.length}}
</div>
{{{{/raw-helper}}}}

There is a better way: \{{foo}}.
Handlebars content may be escaped in one of two ways, inline escapes or raw block helpers. Inline escapes created by prefixing a mustache block with \ . Raw blocks are created using {{{{ mustache braces. You can see this http://handlebarsjs.com/expressions.html#helpers

I would recommend using the AngularJS's data-binding syntax (what looks similar to Handlebars) and have your NodeJS server simply serve the static AngularJS source code. I prefer to offload the templating onto the client and therefore put less stress on your server, not to mention that AngularJS and other MVC frameworks (my favourite is EmberJS) are great for dynamically building the webpage.
I am a fan of Yeoman and here is a generator for building an Angular project served by NodeJS: https://github.com/yeoman/generator-angular

Related

Setting html in jquery with angularjs expression

We are working on a legacy code that has a combination of angularJs, and javascript (jquery). We need i18n. Lots of the changes happening in general js files by setting the HTML on the fly. I am using pipe in the text so the angular take care of it. In some cases, it sets the value as it is instead of using the expression.
$("#exampleId").html("{{'exampleKey' | translate}}");
I am sure combining these technology is not good idea but we cannot rewrite the code for now.
Is there any way to fix this?
#bahar erf. It would make more sense to create a $scope.exampleId variable and use that in the #exampleId element. In the controller set $scope.exampleId and it will automagically update in the view. That's the point of the angularjs framework, it handles those DOM changes so you don't have to use JQuery for those types of changes in the view.
<input ng-model="exampleId" />
or if displayed
<span>{{exampleId}}</span>`

Store template data as a string in Ember

I'm using Ember and an upload plugin. The plugin allows me to overwrite it's HTML template through a property as a string.
$("#fileUpload").dropzone({
previewTemplate: ' some huge html string',
});
Adding in a string of HTML would be difficult to support and look awful so I created an external Handlebars .hbs file which houses the template HTML.
Normally I would populate this template without an issue using $.get(). However, I imagine that Ember has a way to do this intelligently. I've dug through the API and haven't seen anything specific to help me with this.
I would think something like var template = Ember.Handlebars.get('upload.hbs'); would work but it returns an error.
Any help would be appreciated.
Just trying to summarise what you are doing, after clarification from my previous (deleted) answer.
You have a plugin, that accepts a plain html string.
The html string you want to provide to the plugin is very long.
You want to store the string as an external file, to avoid including in your regular code.
The html string is not a Handlebars template though you store it as upload.hbs.
You were hoping that Ember would have a method for loading remote templates, that you could use to avoid using jQuery GET.
No method to load remote templates:
The reality is that Ember does not have a built in method for loading remote template files in their raw format. It does however allow you to precompile handlebars templates to JavaScript that can be included as a regular script tag. But as you are not using a handlebars template pre-compilation would do nothing more than wrap your html string in some JavaScript.
There is no such feature documented.
Nor is there in the source code.
Why Ember.Handlebars.get('upload.hbs') won't work:
This method is used to get the content of locally included templates. That means it only looks for templates that exist in the Ember.TEMPLATES array or from the <script> tags of type text/x-handlebars.
The reason why Ember does not have the ability to load remote template files:
It does not have a method for loading in raw handlebars files because:
Many people use the precompiled handlebars files (which can be loaded as remote JS)
Many people use the inline <script type="text/x-handlebars"></script> tags. It's notable that you cannot use the src attribute of script to pull in a handlebars template, because browsers will only accept src for text/javascript.
Ember relies on jQuery, and as jQuery provides suitable methods GET & AJAX it's trivial to implement in conjunction with Ember.Handlebars.compile("<strong>Hello {{name}}</strong>"), if required.
Your template:
As you are not using a Handlebars template and you are just loading html, the correct approach, as you suspected is simply jQuery GET.
$.get( "dropZoneUploadTemplate.html", function(template) {
$("#fileUpload").dropzone({
previewTemplate: template
});
});
Summary
While it is nice to use Ember where possible, this simply is a jQuery task. Sorry it's not the answer you were hoping for. Maybe in future versions of Ember it will include such as feature.
Making the uploader into an Ember Component:
You could turn your uploader into an Ember Component like this, and combine with the jQuery GET to take care of loading in your html.
App.FileUploadComponent = Ember.Component.extend({
template: Ember.Handlebars.compile("<input type='file' />"),
didInsertElement: function(){
var c = this.$(":file");
$.get("dropZoneUploadTemplate.html", function(template){
c.dropzone({ previewTemplate: template });
});
}
});
This would mean every time you want to use the upload control in your Ember templated view you can simply do:
{{file-upload}}
I hope this helps.

confusion between Jade and Handlebar

Trying out backbone+express with Jade as default templating.
Following a tutorial here(Great tutorial)
Confusion:
Many tutorials about backbone uses underscore template or handlebar to compile and render view.
I was using Jade as default template engine. My question is if I am using Jade then do I have to use another templating like Handlebar or underscore. If not how can I achieve following in Jade
render: function() {
var template = $("#booktemplate").html();
var compiled = Handlebars.compile(template);
var html = compiled(this.model.attributes);
this.$el.html(html);
return this;
},
My assumption: I am thinking Jade and Handle bar both are templating system and can be used alternatively. Is it so?
Why not use both Jade & Handlebar? I dont want to use two different syntaxes
#{} from jade / {{}} from Handlebar
Using Jade on the browser is not really a simple task. Thing is Jade is built for server side and does not support browsers.
This is why you'll often see people using two templates engines (if they use Jade). Some others are just gonna use Handlebars or Underscore everywhere - this is easier because templates engine working in the browser should work on the server. The other way around is not always true though.
Point to be taken here is that before starting to use a template engine, make sure it supports the environment you wish to target. There's plenty of options in term of engine, and this site can help you find one fittings your need: http://garann.github.io/template-chooser/
If you're really like Jade, then, you can use a stack like Browserify and some middleware (Jadeify) to make it work after pre-compilation. But you need to buy into the browserify concept and accept to precompile everything, everytime. You can check this related question for more details: https://stackoverflow.com/a/6623561/1024223

Backbone: managing templates

I'm using underscore template engine for an backbone application. As of now I have over 15 templates in the <head>. Its getting hard to maintain. So far, most of the solutions I seen to manage templates ended up needing them to be js files. That's also a headache, I prefer them to be html files for editing purposes.
I took a look at requirejs and not sure if I need that since it kinda revolves around a more modular approach that I can't say I'm using at the moment (although I will soon).
What will be the best way to manage templates and load/cache them as needed?
Personally we needed a robust solution at my company, so we went with:
Require.js - for module loading
Handlebars - for more powerful templating than Underscore can offer
HBS - an excellent require plug-in from Alex Sexton that handles bringing compiled templates in via Require
With this setup I can keep all of my templates in their own file, and then to use them I have files like this:
define(['template!path/to/someTemplate'], function(someTemplate) {
var MyNewView = BaseView.extend({template: someTemplate});
$('body').append(new MyNewView().render().el);
}
(and as you might guess we have a base Backbone view called BaseView which uses the view's template property to render the view).
Now, all that being said, if you don't need such a robust setup then Require may not be for you. In that case I would do the following:
Put all of your templates in to one or more HTML files; wrap them in script tags, like so:
<script id="dummyTemplate" type='text/template'>
<span>I'm a template!</span>
</script>
Write some code on your server-side to include those HTML files in the main HTML file you send to the client
Write a function which takes a template ID, gets the text of that element, compiles it in to a template, and returns that template (maybe cache the compiled templates if you want ... of course, with Underscore templates I don't think you even need compiling, so you can skip all that).
Use your function to access your templates: $("#something").html(templateFunc('dummyTemplate').template())
This will allow you to store your templates in html files (for syntax coloring), but still access them conveniently in JS. You can also divide your templates between as many files as you want, as long as you can write include logic to bring them in.
If you do opt for Require though, definitely check out the HBS plugin. And if you haven't looked at Handlebars templates yet, you might want to; they're far more powerful than Underscore ones (but like any good templating system, don't allow for too much logic).
Not sure what you mean by it being unmaintainable. Is it just a long list?
You don't need to keep your templates in the head. They can be at the bottom of your body as well. They just need to be defined before you try to use them.
One thing you might look into, depending on the server technology you are using would be to separate your templates into a different HTML file and include it at runtime.

Best way to package multiple jQuery templates in single xHttpRequest?

Update: after another day of digging
into this issue, I have found that the
current jQuery template lib provides
no way to do this. this article
describes a good approach.
I would still like to hear of any
additional thoughts on doing this. The
article linked above requires that the
returned string of templates be
inserted into the DOM. Seems as though
leaving the DOM out of this would be
ideal, and less overhead on the
browser. Imagine a large page, with
multiple composite templates that may
not get used. Although, maybe because
the templates are wrapped in a script
tag, there is only a single DOM item per template? Come on, let's
hear some thoughts...
Using jQuery template libs, what's the best way to combine multiple, related, relatively small templates together? Do you need a single <script> tag for each individual template? What about in the case of dynamically pulling these templates via AJAX? Can I combine these templates somehow?
Consider the following:
<script id="movieTemplate" type="text/x-jquery-tmpl">
{{tmpl "#titleTemplate"}}
<tr class="detail"><td>Director: ${Director}</td></tr>
</script>
<script id="titleTemplate" type="text/x-jquery-tmpl">
<tr class="title"><td>${Name}</td></tr>
</script>
Now because these two templates are very closely related (and one depends on the other) it would make sense to consolidate these into a single AJAX call, and get them both at once. I have a few ideas, but I'd like to know if there is common/best way to do this? Currently I pull in a chunk of HTML, and then do a .find() to get the specific peice of HTML for a template... e.g.:
var templatePackage = fancyAjaxCalltoGetTemplates();
"templatePackage" might then look like this:
<div id="templatePkg">
<div id="movieTemplate">
{{tmpl "#titleTemplate"}}
<tr class="detail"><td>Director: ${Director}</td></tr>
</div>
<div id="titleTemplate">
<tr class="title"><td>${Name}</td></tr>
</div>
</div>
I could then do:
var titleTemplate = jQuery.template('titleTemplate', $(templatePackage).find('#titleTemplate') );
and
var movieTemplate = jQuery.template('movieTemplate', $(templatePackage).find('#movieTemplate') );
...let me know what you think... what would you do?
I like the referenced article in your update, except the assumption that you can't cache templates unless you insert them into the DOM. From the jQuery.tmpl documentation,
"To cache the template when using markup that is obtained from a string (rather than from inline markup in the page), use $.template( name, markup ) to create a named template for reuse. See jQuery.template()."
Using this, we can build a javascript template management system that allows us to load as many templates at a time as we need while keeping the DOM clean. On the client, keep a hash of template objects by name. You can use your favorite object based javascript pattern here, but I would think the structure could be like this:
templates[templateName] = {
templateMarkup: markupFromServer,
loadedAt: Date.now(),
compiledTemplateFunction: jQuery.template( templateName, markupFromServer )
}
Then use the templates to generate HTML like this:
templates['unique-name'].compiledTemplateFunction(inputData)
Then, build an unload mechanism to free up memory:
function unload(templateName) {
delete templates[templateName];
delete jquery.template[templateName];
}
Most importantly, you now have a method of storing multiple templates so you can make requests like: $.get('/TemplateManagement/Render', arrayOfTemplateNamesToLoad, loadManyTemplatesSuccess) to load multiple templates at a time. The only thing we need is a controller TemplateManagement that will take an array of template names as an input and return JSON that pairs a template name with its markup. There are a few ways to do this but it seems to me the most convenient is to define partial views for each template. In ASP.NET MVC 3, you can use this technique and RenderPartial to emit each template's markup into a JSON response. You can either name the partial views the same as the templates or map the names in some custom way.
OK, I read the article you reference in this post. As I see it, his way is probably one of the best ways to load up the template page(s). The only thing I don't like is the asynchronous problems that could crop up, esp. if you need to immediately do some templating before the async get returns... plus any binding issues that could happen before it returns something. In several projects I have done I use his "ancient" SSI (server side includes), but I just use something even easier like:
<% Response.WriteFile("this_page_template_file.html"); %>
You could put it anywhere where you'd place a tag. Like he says, just put in only the templates you need, or maybe include two templates: one is a "base" template with commonly-used items and the second one would have the page-specific ones with template references {{tmpl}}.
Is this even close to an answer? ;-)
[First off, great question. I love this topic]
I have no experience with the plugin "jquery-template-libs", but there is a particular lightweight javascript template plugins that are becoming almost a standard and plays very nicely with jQuery, which is probably better suited for the task than JTL, Mustache:
https://github.com/janl/mustache.js
It's got something that's called a "partial" which is essentially a way to include smaller templates within another one. Which sounds like it will help you out a lot.
On top of that there is a library called ICanHaz.js:
http://icanhazjs.com/
ICanHaz essentially extends Mustache to include built in functionality for templates and works incredibly well.
Mustache/ICanHaz allow you to add templates by variable, by a json call or by using tags. The choice is yours.
I know this is an old question but you might want to take a look at Closure-Templates. They provide the kind of functionality you're after with the added advantage of being compiled into JavaScript at compile-time instead of at run-time in each user's browser.
If you do decide to look into using them then I'd suggest using plovr for building them.

Categories