I haven't been able to find a solid example out there.
Template.registerHelper("itemLookup", function(sku, property){
return Items.findOne({sku: sku})[property];
});
How do I call this on the template?
I want to do something like:
{{ itemLookup sku="i3_4030U" property="title" }}
It should output
"Intel Core i3 4030U"
Do not name template helpers parameters, they will be passed in the same order to your helper function :
{{ itemLookup "i3_4030U" "title" }}
EDIT :
Why then do I see examples online where they are naming the template
helper parameters?
You can name parameters when including another template and you want to set its current data context to something else :
{{> childTemplate param1="A" param2="B"}}
In the child template markup you'll be able to reference {{param1}} and {{param2}}.
Another Handlebars helpers feature available in Spacebars is the "hash" optional argument value you can pass as the last argument to your helper parameters, you can use it like this :
HTML
{{helper "A" "B" namedParam1="C" namedParam2="D"}}
JS
Template.registerHelper("helper", function(param1, param2, options){
console.log("param1 :", param1);
console.log("param2 :", param2);
if(options && options.hash){
console.log("namedParam1 :", options.hash.namedParam1);
console.log("namedParam2 :", options.hash.namedParam2);
}
});
Related
Let's say I have the following Blaze template helper that fetches some objects from a collection:
PackageInCart: function() {
PackageIds = Carts.findOne({SessionId: SessionID}).Packages;
var PackageObjects = Packages.find({ _id: { $in : PackageIds } } ).fetch();
return PackageObjects;
},
The PackageObjects variable contains objects that have a 'priceperday' property with a certain price value. In the Blaze template, I can easily print this value using:
{{#each PackageInCart}}
<div class="price">{{priceperday}}</div>
{{/each}}
However, what if I want to modify the 'priceperday' value from the Helper function before it gets printed in the template? What would be the correct way to do this?
One solution that came to mind was to make a for loop that iterates over the objects and does something like Object.defineProperty() to change the priceperday property into the new value.
I want to know if there's an easier or quicker way using Blaze methods to modify the object property that gets printed with the curly braces.
If you want to do this using blaze you could do this using another helper.
weeklyPrice: function(priceperday){
return priceperday * 7;
}
Which would be called like this
{{#each PackageInCart}}
<div class="price">{{weeklyPrice priceperday}}</div>
{{/each}}
More info about spacebars helper arguments in the docs
everybody :) For example I have something like this:
{{> someCoolHelper
someParam1='someVal1'
someParam2='someVal2'
someParam3='SomeVal3'
someParam4=someAnotherHelper 'value param to this helper'
}}
So I have a function, that computes some value depending on parameter that can be passed in it. So how can I do this?
as you may read in a forum thread at meteor forum this is not possible by now in spacebars.
We began with a new package for chaining methods and arguments but its not released yet. What you could do is to use the WITH element like
Instead something like:
{{> someCoolHelper
someParam1='someVal1'
someParam2='someVal2'
someParam3='SomeVal3'
someParam4=someAnotherHelper 'value param to this helper'
}}
can be managed by:
{{#with someAnotherHelper 'value param to this helper' }}
{{> someCoolHelper
someParam1='someVal1'
someParam2='someVal2'
someParam3='SomeVal3'
someParam4=this
}}
{{/with}}
I don't like it, but sometimes necessary
Tom
P.S.: Or drop Spacebars and use React - you won't have such limitations there.
The placeholder solution until template sub expressions are available in Spacebars is to create an helper returning the adequate value in JS :
HTML
{{> myTemplate param1="A" param2=param2}}
JS
function someOtherHelper(param){
console.log(param);
}
Template.registerHelper("someOtherHelper", someOtherHelper);
Template.myTemplate.helpers({
param2: function(){
return someOtherHelper("B");
}
});
You can pass the output of a helper to another helper using parentheses. Pretty sure this is what you're after:
http://blazejs.org/guide/spacebars.html#Calling-helpers-with-arguments
You can also pass the output of a helper to a template inclusion or other helper. To do so, use parentheses to show precedence:
{{> Todos_item (todoArgs todo)}}
Here the todo is passed as argument to the todoArgs helper, then the output is passed into the Todos_item template.
Something I did in a recent project uses this functionality to allow conditional rendering of CSS classes to a component (stripped down for brevity):
# global helper to provide ternary operator
Template.registerHelper('ternary', (condition, resultTrue, resultFalse) => {
return condition ? resultTrue : resultFalse
})
# in my-template.js:
Template.My_template.helpers({
isComplete(score) {
return score === 1
}
})
# in my-template.html:
{{> some_component class=(ternary (isComplete this.score) "green" "red")}}
I'd like to be able to call (global) template helpers from inclusion template tags.
So this works;
Static version:
{{>volcanoTable pagination=5)}}
But i'd like to get the value of pagination per user by using Template helper function named getPref(key,defaultvalue).
"Dynamic version":
{{>volcanoTable pagination=getPref("pagination",5) }}
which gives error:
Expected space
...ue pagination=getPref('a',5) )}}
Also tried different versions, but they didn't work either;
like {{>volcanoTable pagination=getPref "pagination" "5" }}
Or is there another way to get the same desired results?
You can just create a helper which returns a context object. For example:
Template.myTemplate.helpers({
myPagination: function(n) {
// extract the default pagination for the user
var pagination = Meteor.user().profile.pagination;
if (pagination) {
return {pagination: pagination};
} else {
return {pagination: n};
}
}
});
Which you can use like this:
<template name='myTemplate'>
{{> volcanoTable myPagination 6}}
</template>
In this case, the volcanoTable would get a context of {pagination: 6} only if there was no default pagination property for the user. Of course you could make myPagination a global helper if it's useful outside of this template.
Is it possible to get the length of json object inside the handlebars template using the property .length .
{{json.length}}
If not is it possible to find the length based on the list of keys and then using the .length such as
{{json.keys.length}}
Sample JSON structure
{1232134235423:[Name,Destination,Desc],
2134213214321:[Name],
2342354356634:[Name,Desc]
}
Edit 1:I know this can be achieved by using a custom helper but this length has to be used inside custom if helper. So something like array.length would be useful
If I understand your edit right the problem is not to use another helper but to call it within another helper's call.
Thus, you could use a second helper nested in your custom if-helper call:
{{#customIf (objectLength json)}}
do some stuff...
{{/customIf}}
According to this answer "Getting JavaScript object key list" you can use Object.keys(json) to get all your object's keys.
The new helper objectLength could look like that:
Handlebars.registerHelper("len", function(json) {
return Object.keys(json).length;
});
You can check length of object in handlebars template like this in your template. So HTML will render only when the object have one or more child element.
{
people: [
"abc",
"Alan Johnson",
"Charles Jolley",
],
}
{{#if people.length}}
<p>{{ people}} </p>
<ul class="people_list">
{{#each people}}
<li>{{this}}</li>
{{/each}}
</ul>
{{/if}}
So I don't want to use data functions (let's say I want the final user to only interact with templates and not hardcode javascript.)
If I had this array with n elements how can I filter it so i can get m elements within ractive template ? right now I have this code >> http://jsfiddle.net/t168vymw/4/ which is not working correctly.
requirements:
I cannot use some function to filter, like
data: {filtersomething: function(){...} }
but instead, let the user play with complex array function convertions from the template.
Is ractive yet supporting this ?
If you want to open it up to arbitrary js from the user, then you could do something like this (http://jsfiddle.net/h7ut7cbx/2/):
<input value='{{filter}}'>
<br>
{{# filtered }}
{{.}}<br>
{{/ }}
and
data: {
a: [1,2,3,4,5,6],
filter: 'b%2'
},
computed: {
filtered: function(a, filter){
var fn = new Function('b', 'return ' + (this.get('filter')||'true') + ';')
return this.get('a').filter(fn)
}
}
Ractive doesn't support anything that involves function keyword inside expressions, but there are 3 ways to do this:
data functions,
method calls (calling methods of the ractive instance from inside the template),
filtering data directly in the template.
You said you want all the logic to be in the template so that leaves us with the option #3. For example, if you wanted to display only even numbers from the list, you could do this:
{{ #a }}
{{ #!(this % 2) }}
{{ this }}
{{/}}
{{ /a }}
However, this is usually considered an anti-pattern. It's probably a better idea to allow the user to write custom JS or to provide them with some prepared functions they can use in the template.