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
Related
I'm trying to build a new conditional helper for my Ember application.
Is important mention that I'm using Ember 1.10.1 that uses Handlebars 2.0 and I can't upgrade it, would be great solving the problem with this version of Ember.
Before writing here I tried different solutions and debugged the Ember code a lot, I'm near to the solution but probably I'm missing something.
First of all, I tried with the following approach reading the Handlebar documentation:
Ember.Handlebars.registerHelper('helperName', function(conditional, options) {
if(conditional) {
return options.fn(this);
} else {
return options.inverse(this);
}
});
And here the template:
{{#helperName booleanCondition}}
print true
{{else}}
print false
{{/helperName}}
Everything worked fine calling the fn function but the inversion function (used to render the template of the else branch) was actually an object instead of a function.
Then I started debugging the Ember code and I tried to follow the same approach that Ember uses with the if helper, so I ended up with the following:
Ember.Handlebars.registerHelper('helperName', function(condition, options) {
var permission = Ember.Object.extend({
can: Ember.computed(function() {
return condition;
})
}).create();
Ember.Handlebars.helpers.boundIf.helperFunction.call(this, ["can"], permission, options, options.data.buffer);
});
can is the property bound to the if, used to change the template if the property changes, since we are using the boundIf version of the if (that does what I just said).
The problem of this solution, that imho could be the nearest to be correct, is that the property is not computed correctly and the helper prints always the false value.
I debugged really a lot without making it working, so any help would be very appreciated and I hope this could be useful for someone else as well.
If what you're trying to do is build a conditional approach that supports authorization questions, you should take a look at ember-can. It is an Ember-CLI addon (whereas it looks like you are doing globals) but older versions worked with Ember 1.10. You should be able to reference what they do there and pull it in on your setup
The good news is you are on Ember 1.10!
This means you have subexpressions. And its simple to create a bound non-block helper:
Ember.HTMLBars._registerHelper('foo', function(bar) {
return bar == 'bar';
});
To use it as a block helper combine it with the {{#if}} helper:
{{#if (foo model)}}
in if
{{else}}
in else
{{/if}}
I am following a template for dynamically choosing which model, route, controller to render with a render helper, as outlined in this question (and elsewhere). My problem is that we want to run with the Ember.ENV.RAISE_ON_DEPRECATION flag set, to catch problems before they develop into upgrade nightmares. I am calling Ember.Render from a handlebars helper, like this:
Ember.Handlebars.registerBoundHelper('renderModuleEdit', function(callingContext, module, options) {
var modelName = callingContext.get('type').get('modelName');
return Ember.Handlebars.helpers.render.call(callingContext, "edit_" + modelName, modelName, options);
});
The template has this code in it:
{{#each module in modules}}
<div class="tab-content" {{bind-attr class="module.active:active"}}>
{{renderModuleEdit module module}}
</div>
{{/each}}
The problem is that render fails on the test for 'quoteless parameters', even though I'm using call() on it, rather than a direct handlebars template syntax. The test is defined in the source on this line. The actual test is options.types[0] !== 'ID', and while the options parameter is available in the register helper function (first code block above), and thus I would be able to change the 1st type away from 'ID', I'm not sure what I can change it to that wouldn't cause something else to subtly break later. The error message comes through as:
Uncaught Error: Using a quoteless parameter with {{render}} is deprecated. Please update to quoted usage '{{render "edit_Intro"}}.
As I am not using {{render edit_Intro}} to make this call, I have no idea how to correct this. If I change the template code to {{renderModuleEdit 'module' 'module'}}, then the parameters to my renderModuleEdit come through as strings of 'module' rather than the model instance I need.
I feel like I have no understanding of what this test is actually for and what the 'quoteless' vs 'quoted' parameters even mean. Can someone explain this? Is there a way around this deprecation warning for calling render from a registered bound handlebars helper like this?
A dirty solution, but working for now:
Ember.Handlebars.registerBoundHelper('renderModuleEdit', function(callingContext, module, options) {
options.types[0] = "STRING"; // FIXME: hack
var modelName = callingContext.get('type').get('modelName');
return Ember.Handlebars.helpers.render.call(callingContext, "edit_" + modelName, modelName, options);
});
I also, wasn't able to find a proper fix yet :-/
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'
});
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
};
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');