Why won't my Ember template render? - javascript

Here's a fiddle for this question (add/remove single slash on line 5 and re-run)
Basically, two ways of binding (proper term?) my application template. I would expect both ways to work, but one works, and one doesn't.
Works
this.register( 'view:application', Ember.View.extend());
this.register( 'template:application', Ember.Handlebars.compile( 'Hello, world!' ));
Broken
this.register( 'view:application', Ember.View.extend({
'template': Ember.Handlebars.compile( 'Hello, world!' )
}));
This seems to be the case for all resources/routes, not just at the application level.
So, why doesn't the second method work?
Edit: Here's a another fiddle that shows a Handlebars view helper successfully using method 2 (broken) above. It seems it's only an issue for route views.
Edit 2: Thanks to c4p Here's an Issue on Github

Have a look at this related question.
Short summary:
Ember expects to find templates in the global variable Ember.TEMPLATES. When you use Ember.Handlebars.compile, the compiled templates are put into the global variable Handlebars.templates.
If you want to use the compiling this way, you have to do something like this:
Ember.TEMPLATES['posts-template'] = Ember.Handlebars.compile('I am the template');
App.PostsView = Ember.View.extend({
templateName: 'posts-template'
});

Related

How to call an angular directive within an a tag whilst passing a variable

I would like to do something like this:
<a <myDir myVar="someInput"></myDir>>Call myDir</A>
However I'm realising you can't nest a directive within an a tag and set parameters this way.
I'm actually using jade though. I call the directive fine with.
a(myDir) Call myDir
but am unsure how to pass the variable to the directive. I've tried the equivalent jade to the above html, which is this:
a(myDir(myVar="someInput")) Call myDir
As its an optional parameter I use the '=?' syntax in the directive.
However the issue is definitely the syntax for calling the function in jade.
So after much failure this is how you do it.
// In the HTML/Jade
a(myDir info="someInput")
// In the Directive
scope: {
info: '#?info'
}
Check out this question and #aifarfa's answer for an example. Though the question is different it's a perfect example of what I wanted to do.
How to call directive from template html in angularjs

How to get Template.dynamic to work

I tried ,but i cant get it to work! i changed the value of Template in many ways, but still not working.
In html >>
<body>
{{> Template.dynamic template=Template data=data}}
</body>
In Meteor.isClient >>
Template.body.helpers({
'Template': function() {
return page.template;
},
'data': function() {
return page.getTemplate();
}
});
I'm using the last version, 1.1.0.2
A few suggestions:
Make sure page.template is a string. It should be the name of the template and not a template instance.
Make sure page.getTemplate() is a simple object - this should be a template context and not a template instance.
It may be that the name Template for your helper causes some kind of conflict. Try templateName or something more descriptive.
You asked that in another thread as well and I made a MeteorPad for that:
http://meteorpad.com/pad/oPhK4KqjiSztRSa9K/SimpleDynamicTemplateSwitch
Cheers,
Tom
Ref to the similar thread: How to force Template.dynamic to re render

typeahead.js binding to template issue

I am binding my typeahead for users images to hogan template and the code actually works fine but I am getting errors in console as it tries to get a resource: localhost:####/%7B%7BuserBlankImgUrl%7D%7D
The only thing that make sense is that it is trying to bind to the template value instead of waiting for a value.
Full disclosure: My app is using DurandalJS and knockoutJS pretty heavily but I tried to just show the relevant code below. I will include more based on suggestions.
Template:
<img class="quarc-avatar-list-item" src="{{userBlankImgUrl}}" />
JS:
self.userImgUrl = ko.computed(function () {
return avatar.fromGravatar(self.email(), self.gender());
});
Other things I have tried include:
Wrapping the template in null checks so doesn't try and bind.
When I remove the template hmtl I don't get the resource error in my browser console
Tried to learn more hogan and typeahead options to look for other options. Not sure if something like a pre-render or setting default "local" values would help?
Thanks,
-Chris
The first thing I notice is your self.userImgUrl is not the same userBlankImgUrl used in your template - if this is intentional it's not clear from your posted snippets.
However, at some point your scripts are outputting the template without running it through your template object's render() method. The bad request is caused by the src attribute for the/an image tag litterally being "{{userBlankImgUrl}}". I'm guessing you're testing your app on a local server, so the address it looks up is http://localhost/.../{{userBlankImgUrl}} (unless the ### in your question isn't just you shortening/hiding the path and it really is requesting from localhost:####/%7B%7BuserBlankImgUrl%7D%7D - either way the problem (or at least part of it) is the same).
Hogan.js removes any undefined handlebar'd variables that appear in templates it renders:
var template = Hogan.compile(
'<img class="quarc-avatar-list-item" src="{{undefinedVariable}}" />'
);
console.log( template.render({var1: "Test", var2: "Again"}) );
Will output to console:
<img class="quarc-avatar-list-item" src="" />
If anything appears in the src attribute or in the place of any {{templateVar}} where a null or undefined value was given then you know your template was outputted without going through the proper render method.

Escape double braces {{ ... }} in Mustache template. (templating a template in NodeJS)

I'm trying to template a template, like below:
{{{
{
"name" : "{{name}}",
"description" : "{{description}}"
}
}}}
{{{debug this}}}
<h1>{{name}}</h1>
Where I want to triple brackets to stay, but double brackets to be replaced with the JSON passed in. Anyone know the best way to do this without writing post-process JS code, and if not, is there a good nodeJS template engine for this type of scenario?
As described in this Question handlebars doesn't support changing the delimiters. But you can escape the double braces with a backslash like this:
HTML:
... \{{ myHandlbarsVar }} ...
You can switch delimiters to something that won't conflict with the triple mustaches, like erb-style tags:
{{=<% %>=}}
{{{
{
"name": "<% name %>",
"description": "<% description %>"
}
}}}
{{{debug this}}}
<%={{ }}=%>
Note that you can do this as many times as you like throughout your template. Any time you run into something that conflicts, pick a new set of delimiters :)
You can also assign Mustache.tags = ["[[", "]]"]; before your template compilation.
http://jsfiddle.net/fhwe4o8k/1/
e.g.
$(function () {
Mustache.tags = ["[[", "]]"];
var template = $('#test').html();
Mustache.parse(template);
var rendered = Mustache.render(template, {test: "Chris"});
$('#content-placeholder').html(rendered);
});
another option is create a helper for outputing curly brackets.
Handlebars.registerHelper('curly', function(object, open) {
return open ? '{' : '}';
});
and then use it in the template like this:
<script id="template" type="text/x-handlebars-template">
{{curly true}}{{name}}{{curly}}
</script>
which then outputs:
{Stack Over Flow Rocks}
The template contains HTML, so you could use HTML-Entities, for example the ASCII-codes 123 and 125 for braces:
{{{myValue}}}
I just wanted slightly different approach. I have tried few other other ways and here are few things which I didn't like about them:
Changing Angular default {{obj.property}} brackets to something else is a bad idea. Mainly beacause as soon as you start using third party components which are not aware of you non standard angular configuration, bindings in those third part components will stop working. Also worth mentioning that AngularJS team doesn't seem to want to go the route of allowing multiple binding notations, check this issue
I quite like Mustache templates and don't want to switch the whole project to something else because of this small issue.
Quite a few people recommend not to mix client and server side rendering. I don't fully agree, I believe if you are building a multipage website which has few pages with angular and some other which are static (something like about us or Terms and Conditions pages) it is perfectly fine to use server side templating to make maintaining those pages easier. But that said, for parts which are Angular you shouldn't mixing server side rendering.
Ok no my answer:
If you are using NodeJS and Express you should be to the following:
Replace bindings {{}} in your angular part with something like {[{}]} (or something completely unique)
Now in you route add a callback to you render method:
app.get('/', function(req, res){
res.render('home', {
title: 'Awesome Website',
description: 'Uber Awesome Website'
}, function(err, html){
var htmlWithReplacedLeftBracket = html.replace(/{\[{/g, '{{');
var finalHtml = htmlWithReplacedLeftBracket.replace(/}\]}/g, '}}');
res.send(finalHtml);
});
});
This should allow you to use Mustache together with AngularJS. One improvement you could do is extract that method into a separate module to reuse across all routes.
This is a good solution I have found for this type of problem where you can easily switch delimiters in the template settings in runtime:
http://olado.github.com/doT/
You can do the RegEx settings like this:
doT.templateSettings = {
evaluate: /\{\{([\s\S]+?)\}\}/g,
interpolate: /\{\{=([\s\S]+?)\}\}/g,
encode: /\{\{!([\s\S]+?)\}\}/g,
use: /\{\{#([\s\S]+?)\}\}/g,
define: /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,
conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,
iterate: /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,
varname: 'it',
strip: true,
append: true,
selfcontained: false
};

Why doesn't this emberjs template update?

I'm learning emberjs and I've done a pretty simple example. The HTML template is:
<script type="text/x-handlebars">
Hello <b>{{App.appOwner}}</b>
</script>
And then the javascript is:
App = Ember.Application.create({
appOwner : 'Erik'
});
App.appOwner = 'Tom';
Which does pretty much what you expect. The emberjs.com documentation says templates are auto-updating -- so I added this:
$(document).click(function() {
console.log('HERE!');
App.appOwner = 'Alphonse';
});
Which quite unexpectedly failed. I had added the console.log just to make sure the click handler was being called, which it was. Why doesn't it update?
You need to use .set() mutator method, because javascript doesn't have facilities to intercept the direct properties changes:
App.set('appOwner', 'Alphonse');

Categories

Resources