After a lot of effort I have implemented handlebarsjs to a test site that displays users data as they enter it.
To display the users input in different templates styles, I have had to repeat the same handlebarsjs code several times in the same form.
Is there a way to place the repeated handlebars code in an external page and then include this external page in place of the repeated handlebars code?
I am unsure of the syntax or even if this approach is possible with handlebarsjs (I have tried several things - but cannot get this working).
Here is the culled repeated code that I have:
{{# if address_style_one_line }}
{{! address is to be displayed across one line - replaced line breaks with line space }}
{{# if address_style_01 }}
....
{{else}}
{{# if address_style_02 }}
....
{{else}}
{{! address is to be displayed across more than one line - use this format as the template for the address scross one line style }}
{{# if address_style_01 }}
....
{{else}}
{{# if address_style_02 }}
....
{{/if}}
You should be able to accomplish this with partials. Partials allow you to reuse templates within other templates.
Documentation:
Basic usage: http://handlebarsjs.com/#partials
Other features: http://handlebarsjs.com/partials.html
Rough example:
<script id="address-template" type="text/x-handlebars-template">
{{# if address_style_one_line }}
{{> address}}
{{else}}
{{> address}}
{{/if}}
</script>
<script id="address-partial" type="text/x-handlebars-template">
// repeated template goes here
{{! address is to be displayed across one line - replaced line breaks with line space }}
{{# if address_style_01 }}
....
{{else}}
{{# if address_style_02 }}
....
</script>
<script type="text/javascript">
$(document).ready(function() {
// register partial
Handlebars.registerPartial("address", $("#address-partial").html());
});
</script>
Related
I realise that this has been brought up before, and that Template.dynamic isn't designed to take in a parameter if its template parameter is a helper.
But here is what I would like to do:
// a global helper that composites the template's name using domain-specific and global parameters
Template.registerHelper('templateName', function (name) {
return name + Session.get('someVariable');
});
<!-- use case: a template calling two dynamic ones -->
<template name="someTemplate">
<div class="some-class">
{{> Template.dynamic template=templateName 'title' }}
</div>
<div class="another-class">
{{> Template.dynamic template=templateName 'content' }}
</div>
</template>
This pattern is extremely DRY and it avoids having to set up nested conditionals and rewrite quasi-identical templates each with minimal changes.
Right now, I've got this:
Template.registerHelper('templateName', function () {
var dt = this.dName || Template.parentData().dName;
return dName + Session.get('someVariable'));
});
<template name="someTemplate">
{{> segment dName="title"}}
{{> segment dName="content"}}
</template>
<template name="segment">
<div class="some-class">
{{> Template.dynamic template=templateName }}
</div>
</template>
It works, but it isn't ideal, because;
confusion-prone need to include the parameter for the dynamic template's name in the parent template's call
only ever being allowed one Template.dynamic per template due to one parameter, leading to scalability issues
putting the dName parameter in the template's data context is mixed in with local data, requiring the hacky check whether it's accessible in the current one or the parent's
any further complexity in the DOM requires lots of nested conditionals for parameters or many slightly different static templates, leading to bloat
Are there plans to add this functionality? Am I going about this the wrong way? Did anyone else run into these issues?
Thanks for reading.
There is a trick to doing this with {{with}}. See here:
https://forums.meteor.com/t/pass-argument-to-helper-in-template-dynamic-call/3971
I'm wondering if it is possible to nest multiple if/else statements using handlebars? All my attempts so far have resulted in compile errors, what I'd like to do is as follows:
{{if address}}
<ul>
<li>address.line1</li>
<li>address.line2</li>
{{if address.line3}}<li>address.line3</li>{{/if}}
{{if address.line4}}<li>address.line4</li>{{/if}}
{{else}}
No address given
{{/if}}
Is what I'm attempting here achievable? It always results in parser errors, thusfar I've got around it by writing a helper to deal with spitting out the address (which deals with conditionality of line3/line4 in javascript):
{{if address}}
{{formatAddress address}}
{{else}}
No address given
{{/if}}
While this works, it would be nice not to have to write a helper function for every instance of this sort of simple conditionality.
I believe ifs need a preceding #
Try this.
{{#if address}}
<ul>
<li>address.line1</li>
<li>address.line2</li>
{{#if address.line3}}<li>address.line3</li>{{/if}}
{{#if address.line4}}<li>address.line4</li>{{/if}}
</ul>
{{else}}
No address given
{{/if}}
I do not know if this is specific to the requirejs handlebar plugin but when I have a template like :
<h1>abc</h1>
{{#if testcondition1}}
<h1>def</h1>
{{/if}}
{{#if testcondition2}}
<h1>ghi</h1>
{{/if}}
<h1>xyz</h1>
I get a empty line if one condition is false.
so like:
<h1>abc</h1>
<h1>ghi</h1>
<h1>xyz</h1>
and not
<h1>abc</h1>
<h1>ghi</h1>
<h1>xyz</h1>
Is this the expected behavior?
I'd like to get no lines without recurring to string manipulation after the template compilation. I know that lines get ignored in html but this can be really annoying especially in loops.
If you look at the newline placements in your code:
<h1>abc</h1>\n
{{#if testcondition1}}\n
<h1>def</h1>\n
{{/if}}\n
{{#if testcondition2}}\n
<h1>ghi</h1>\n
{{/if}}\n
<h1>xyz</h1>\n
You can see that if the first condition is false, the code without the skipped branch is:
<h1>abc</h1>\n
\n
{{#if testcondition2}}\n
<h1>ghi</h1>\n
{{/if}}\n
<h1>xyz</h1>\n
which gives you two newlines in a row.
I've got a few templates which list items (log lines, users) and style them accordingly in tables. Now I've added a "search" page which searches for a string in different item types and displays them on one page. In terms of layout, I want to reuse the original templates, but obviously with the data returned by the search.
How can I do that without duplicating the template itself in the HTML file?
Put another way: How can I use the actual data from the top-level template in the sub-templates.
Small example:
<template name="user_list">
{{#each user_list}}
</template>
<template name="users">
{{> user_list}}
</template>
<template name="search">
{{> user_list}}
{{> group_list}}
</template>
In .coffee:
Template.users.user_list = ->
[a,b,c,d]
Template.search.user_list = ->
[b,c]
Maybe this is an easy one, which would show how little I really understood about Meteor.
Just put the template you want to use inside the {{#each}} statement. Then each item in the array will be the context for that inner template.
HTML file
<template name="users">
<ul>
{{#each UserArr}}
{{> userItem}}
{{/each}}
</ul>
</template>
<template name="userItem">
<li>{{username}} {{profile.name}}</li>
</template>
JS file
Template.users.UserArr = function()
{
return Meteor.users.find({});
};
another solution is to put your request in a Session attribute and check for its existence when querying for the users. By default Session.get("userQuery") would return undefined but once you enter something in the search field you change that with Session.set("userQuery", {type: "something"})
Now in the coffeescript you could say:
Template.users.user_list = ->
if(Session.get("userQuery"))
[a,b,c,d]
else
[b,c]
or alternatively use a MiniMongo query because it is much nicer :-)
the nice thing is that your HTML will rerender because it is reactive to the Session's content.
I am using Handlebar.js as my templating engine. Now I want to comment out some of the blocks in my handlebar templates. But then I realized that Handlebar doesn't ignore the expressions inside the Handlebar comment block. Any workaround for this?
The newest version of Handlebars has block comments support :
{{!-- {{commented expressions}} --}}
https://github.com/wycats/handlebars.js/commit/a927a9b0adc39660f0794b9b210c9db2f7ddecd9
Just add an exclamation mark after the opening brackets.
Normal Expression:
{{expressions}}
Commented Expression:
{{!expressions}}
Use this way in your handlebar template file.
<div class="entry">
{{!-- only output author name if an author exists --}}
{{#if author}}
<h1>{{author.firstName}} {{author.lastName}}</h1>
{{/if}}
</div>
The comments will not be in the resulting output. If you'd like the comments to show up, then use HTML comments.
<div class="entry">
{{! This comment will not be in the output }}
<!-- This comment will be in the output -->
</div>
refer this link to
Two ways to comment on handlebar.js
single component:
{{!fixedTop=true}} --> comments the whole content inside the brackets
Multiple component:
{{!--fixedTop=true
alignment=true--}} --> comments the whole content until end with "--"
offical site said
"You can use comments in your handlebars code just as you would in your code. Since there is generally some level of logic, this is a good practice.
The comments will not be in the resulting output. If you'd like the comments to show up just use HTML comments, and they will be output.
Any comments that must contain }} or other handlebars tokens should use the {{!-- --}} syntax."
Check the site https://handlebarsjs.com/guide/#evaluation-context
Use this code:
{{#data}}
<!-- enter comments here -->
<p>{{name}}</p>
{{/data}}