To the handlebars (version 1.0.0-rc.3) template I am passing two variables , one is the json and the other one is the string containing the current language on site.
self.template = template({ data: self.model, lang:self.lang });
Then inside the template file I have the following structure:
{{#each data}}
//this is working
{{../lang}}
{{#if this.title}}
{{this.desc}}
//i've tried this
{{../lang}}
//and this
{{lang}}
{{/if}}
{{/each}}
...but I couldn't access the lang value inside the if statement. What am I doing wrong?
I know you already solved your issue with a workaround but registering a Helper for doing a native way is cumbersome.
The thing is that every Handlebars helper overwrites the context and nest the new one inside the parent one, so you have to go up uone step further, like a UNIX like directory.
So, to access lang inside an each->if you have to use:
{{ ../../lang }}
I've find a solution by creating a handlebars helper function:
Handlebars.registerHelper('language', function() {
return self.lang; });
Then in the template i could use {{language}}
where ever I want.
Related
I have a Handelbars app that loads data from javascript and partials for the templates. To get the templates to work I use the following in the Javascript:
var data = require('partials/data.js');
Handlebars.registerPartial('data', data);
Then in my partial I am able to do:
{{> data }}
I have a Handelbars variable I can use in my main template but I want to pass it down to the partial. With my other partials that don't register via the Javascript this is possible. I am assuming I need to pass this variable down like I do the templates?
As per the handlebars documentation, you should be able to simply pass the variable down as a parameter, like so:
{{> data parameter=variable }}
I have a few lines of markup that I'd like to avoid keeping in an external partial file, but it should be rendered based on a variable value, either IN_PROCESS or DONE. I can make inline partials and render them based on static names:
{{#* inline "IN_PROCESS"}}IN_PROCESS{{/inline}}
{{#* inline "DONE"}}DONE{{/inline}}
{{> IN_PROCESS }}
{{> DONE }}
However I cannot figure out how to combine that with the () dynamic values syntax I have read about here.
So something like,
{{> (data.status) }}
└─────────┘ data.status would be either 'IN_PROCESS' or 'DONE'
Is this possible?
I believe you want something similar to this:
{{#* inline "IN_PROCESS"}}IN_PROCESS{{/inline}}
{{#* inline "DONE"}}DONE{{/inline}}
{{> (lookup . 'status')}}
{{> (lookup . 'status')}} will look through the JSON data object for its status attribute.
That is if you're passing your data in something like this:
var template = Handlebars.compile(**your source**);
$('body').append(template(data));
JSFiddle Example
The dot represents the data object that has been passed into the template function. The template function has no way of knowing what the object's name was:
template(inputData){
// This function wouldn't know that inputData.status was originally data.status
}
var data = {status: "DONE"};
template(data);
The dot is therefore used to tell "template" when searching for a parent that inputData should be the parent and we're looking for "status" as a child. I believe that is the use of it. I actually can't find any documentation regarding its use but all lookup's seem to be in the format lookup parent child so I assume that's the reasoning.
Lets say I have an array of widget objects on my controller and each widget object has member variable that is assigned the name of a component class. How can I get my template to invoke that component?
//widgets[0].widget.componentClass="blog-post"
{{#each widget in widgets}}
{{widget.componentClass}}
{{/each}}
Obviously the above example just spits out a series of string versions of the widget component classes. This however does work (as long as you got everything set up right):
//widgets[0].widgets.viewClass="blogPost"
{{#each widget in widgets}}
{{view widget.viewClass}}
{{/each}
That was our previous implementation, but we weren't happy with it. We're currently using a custom {{renderWidget ...}} tag with a handlebars helper as described here: Calling Handlebars {{render}} with a variable name. The default render helper has a similar problem where it would not invoke a render on the contents of a variable name. I'd be willing to write a custom component handlebars helper but I can't even figure out where to start. Thanks.
I tried this and it seems to work, but its just a lot of guesswork on my part:
Ember.Handlebars.registerHelper('renderComponent', function(componentPath, options) {
var component = Ember.Handlebars.get(this, componentPath, options),
helper = Ember.Handlebars.resolveHelper(options.data.view.container, component);
helper.call(this, options);
});
and you use it the same way:
{{#each widget in widgets}}
{{renderComponent widget.componentClass widget=widget}}
{{/each}}
In Ember 1.11, the new component helper allows you to do this:
{{#each widget in widgets}}
{{component widget.componentClass}}
{{/each}}
As of today, Jan 19th, 2015, 1.11 is not a stable release but this feature is in the canary version.
Sounds like I've run into a lot of the same problems as you. All components are registered as top level helpers, which means you can do a similar method to the one you linked of creating a handlebars helper that does the lookup. Like this:
Ember.Handlebars.registerHelper('lookup', function(component, options) {
component = Ember.Handlebars.get(this, component, options);
Ember.Handlebars.helpers[component].call(this, options);
});
Then in your template:
{{#each widget in widgets}}
{{lookup widget.componentClass}}
{{/each}}
Here's a jsbin with a working example: http://jsbin.com/ucanam/2482/edit
Hope that helps!
-- edit --
For some reason, the new version of handlebars makes calling helpers from other helpers impossible. Instead you can lookup the template through the Ember.TEMPLATES global. I've updated the JSBin to use this method.
You can also get the template via options.data.view.templateForName(component), but it feels a bit more brittle than Ember.TEMPLATES.
-- edit 2 --
It's changed again. Ember.Handlebars.resolveHelper is now the correct way to do it. See #StrangeLooper's answer.
If you are using Ember CLI and Coffeescript here is a version for that. Create the following file in app/helpers/render-component.coffee:
renderComponent = (componentPath, options)->
helper = Ember.Handlebars.resolveHelper(options.data.view.container, componentPath)
helper.call this, options
`export { renderComponent }`
`export default Ember.Handlebars.makeBoundHelper(renderComponent)`
From there, you can call {{render-component "foo-bar"}} from a template.
Since the Ember ecosystem is ever changing, here is the version I tested it on:
Ember-CLI v0.0.43
Ember v1.7.0
Handlebars 1.3.0
As the Meteor docs state,
A template instance object represents an occurrence of a template in the document. It can be used to access the DOM and it can be assigned properties that persist as the template is reactively updated. [...] you can assign additional properties of your choice to the object.
How can these properties be accessed from Spacebar templates?
It's cumbersome to have to define helpers that do nothing more than
return Template.instance().myProperty
Just like #apendua said in comment, you can use global helper, this worked for me:
Template.mainPage.onCreated(function(){
this.test = new ReactiveVar('stackoverflow');
});
Template.registerHelper('instance', function(context, options) {
return Template.instance()[context].get();
});
and in HTML
{{instance 'test'}}
You could probably use Template.currentData() as well.
Edit
According to this article you can do in HTML something like:
{{Template.instance.test.get}}
so there is no need for global helpers, and it is accessible from Spacebars so no helpers required
OP wants to access the data directly without any helpers. You will need to store the data in Template.currentData() or Template.parentData(n). Anything in those can be accessed as {{myData}} or {{../myParentData}}, respectively.
I think you can use {{#with}}{{/with}}
for example
{{#with getObject}}
<h1>{{prop1}}</h1>
<h2>{{prop2}}</h2>
{{/with}}
and in helper
getObject:function(){
return {prop1:'some text prop1',prop2:'some text prop2'}
}
To the handlebars (version 1.0.0-rc.3) template I am passing two variables, one is the json and the other one is the string containing the current language on site.
self.template = template({ data: self.model, lang:self.lang });
Then inside my template file I am having issues with displaying lang variable inside the if statement. So the structure of my template is the following:
{{#each data}}
{{#if this.title}}
...some html...
<a class='links' href="{{../lang}}/work/{{this.id}}">View Project</a>
...some html...
{{/if}}
{{/each}}
I am unable to access the lang variable only inside the if statement and outside is being shown properly...
Please advise...
I've found a solution by creating a handlebars helper function:
Handlebars.registerHelper( 'language'
, function() {
return self.lang;
});
Then in the template I can use {{language}} where ever needed.