I am checking if there is anyway that I can use the result of one helper function in another helper function and how can I use it, for example, I am looping through as below
{{#each v.NOVNumber as |vv iindex|}}
And then if I am getting another element as below, using the same index:
{{get v.NOVNoticeTypeName iindex}}
Can I use this element that we have got in a statement like below, to check if that is first or last element etc?
{{#if (isFirst v.NOVNumber vv)}}
You you can use helpers together to create more powerful functions. Ember Composable Helpers provides both a good pattern for using helpers together as well as the specific has-next and has-previous helpers that you need to know if an element is first of last.
An example using has-next
{{#if (has-next page pages)}}
<button>Next</button>
{{/if}}
Related
I have two arrays NOVNoticeTypeName and NOVNumber, they both have the same number of elements, now I want to loop through one of them and print the values side by side as below:
{{#each v.NOVNoticeTypeName as |nntn index|}}
{({{v.NOVNoticeTypeName.[index]}} {{v.NOVNumber.[index]}})
{{/each}}
I understand looping is a mess in the Ember handlebars.
How can I achieve this?
First of all I don't share your opinion that looping is a mess in Ember templates. Would be great if you don't put such opinions as a facts. Especially if it comes without any argument.
What you want to achieve could be done with a combination of an {{each}} loop and a template helper. As your example already shows {{each}} loop yields the current value and index. You can't access an array element directly using the index as in JavaScript array[index] in an Ember template but you could achieve the same using a template helper. A template helper, lets call it {{object-at}} that gets an index as first and an array as second argument and returns array[index].
Lets see an example how that would work:
{{#let (array 'a' 'b' 'c') as |letters|}}
{{#let (array '1' '2' '3') as |numbers|}}
<ul>
{{#each letters as |letter index|}}
{{letter}} {{object-at index numbers}}
{{/each}}
</ul>
{{/let}}
{{/let}}
Such a template helper wouldn't be to complex. But you don't have to worry at all, cause it's already available as part of ember-composable-helpers.
In a JsRender template, blocks can create variables, so I could write this:
{{if true ~myVariable=myExpensiveFunction()}}
{{:~myVariable}} {{:~myVariable}}
{{/if}}
However, the bogus if is annoying. Is there a better way?
If you can initialize myVariable outside the template, then you can make it a helper variable, and pass it in:
var html = myTmpl.render(data, {myVariable:myExpensiveFunction()});
If you need to initialize in a specific template/data context then as you say, you can use contextual parameters, which are scoped to any template block. Use the tag that wraps that context.
If the context is is top-level in a template, then:
either this is top-level data and you can pass in a helper as above
or it is a 'partial' template rendered from anothor (layout) template, using {{someTag tmpl=.../}}, in which case you can set up your contextual parameter from the calling tag in the other template
or else it is rendering against an array
For that last case you can use {{include}}:
{{include ~myVariable=myExpensiveFunction()}}
{{:~myVariable}} {{:~myVariable}}
{{/include}}
or you can call with noIteration set to true:
var html = myTmpl.render(data, [helpers,] true);
and then wrap in {{for}}:
{{for ~myVariable=myExpensiveFunction()}}
{{:~myVariable}} {{:~myVariable}}
{{/for}}
EDIT:
In your particular case, based on your comments added below, you need to initialize in the context of an item block within a {{for someArray}} - in order to get the item data.
(Actually your item block is a 'partial' template called using {{for someArray tmpl=...}}, but the basic problem is the same).
In this scenario you will indeed need to add an {{include}} wrapper, at top-level (for you) or within the {{for}} if not doing template composition.
So there is a template file that is generating a few different layouts for a component in my webpage with different variables dictating sizes and whatnot. So in order to reduce the number of files in the project, I'm trying to reuse the template files for code snippets instead of having dedicated files for them. Through sub expressions, I've had the idea of doing something like this:
{{ escape (template var1=var1 var2=var2 var3=var3) }}
where escape is a helper that takes a string and escapes it (funnily enough), and:
(template var1=var1 var2=var2 var3=var3)
is supposed to have the same effect as {{> template var1=var1 var2=var2 var3=var3 }}, returning complete markup presumably as a string.
The helper doesn't seem to be receiving any string since running typeof on the parameter is returning undefined. I had assumed since {{> template var1=var1 var2=var2 var3=var3 }} is being used higher up in the file, that was registering it for use within the rest of the file, but now I'm thinking that's not how Handlebars does its thing.
Is it possible to retrieve the partial like this or does it need to use the {{> syntax (which doesn't work)?
At the time I asked this question, I was a bit confused with how a context was applied to a partial programmatically. Now that I've done a bit more research (I did try before asking but got nowhere), I now know that Handlebars.compile(partial) will return an object for the given partial and allow a context to be given through partial(context) which should be returned.
Sample Code
function escape(partial) {
let compiledPartial = Handlebars.compile(partial);
let context = { greeting: "Hello World!" };
return compiledPartial(context);
}
How would I use a while loop in meteor blaze?
I tried using {{unless}} but that did not work. This is what I tried:
<template name="homePage">
<h2>Welcome to home page! </h2>
{{#unless numberOfDays 0}}
<span>hi</span>
{{numberOfDays--}}
{{/#unless}}
</template>
It did not work at all.
There is no #while in spacebars, the templating engine that is default in meteor-blaze.
The #unless keyword is a negated #if, a conditional on something not being truthy. The unless block is not a loop, it can only run once. Like if, the block will either run or not run. The #unless runs if the condition is not truthy.
The only loop construct is #each. You could emulate the behavior of a for or while loop by calculating the results outside the template and placing them in an array variable. In the template, call #each on the array variable.
Although writing a customized handlebars block helper can be used to make custom iteration such as a while loop, Meteor's spacebars is a fork of the handlebars code, and may require a slightly different syntax.
For most simple uses, #each is enough . Reformatting data will often allow #each to be used in a natural way.
From the Spacebar docs
#Each
An #each template tag takes a sequence argument and inserts its content for each item in the sequence, setting the data context to the value of that item:
<ul>
{{#each people}}
<li>{{name}}</li>
{{/each}}
</ul>
The argument is typically a Meteor cursor (the result of collection.find(), for example), but it may also be a plain JavaScript array, null, or undefined.
An "else" section may be provided, which is used (with no new data context) if there are zero items in the sequence at any time.
I have a very simple template loop:
{{#each}}
{{title}}
{{/each}}
Fact is, my title can appear in my data multiple times (of course other parts of the record change) but I want to make sure that there are no duplicates for a given property (in this case title). Is there any way to put some logic inside the template to make sure to exclude duplicates?
I tried using an Handlebar Helper, but I really didn't make much progress with that.
You should put a computed property on the controller that's backing the template. Ember has a method uniq that will return the unique items in the array.
uniqueItems: function(){
return this.get('model').getEach('title').uniq();
}.property('model.#each.title')
http://emberjs.jsbin.com/IMOMoliB/5/edit