I'm create handlebars helper:
export default Ember.Handlebars.registerHelper('if-eq', function(v1, v2, options) {
if (this.get(v1) === this.get(v2)) {
return options.fn(this);
}
return options.inverse(this);
});
And execute like this:
{{#each item in model.cons }}
{{#if-eq model.currentUser.id item.record_poster_id}}
<div class="td author current">{{model.currentUser.name}}</div>
{{else}}
<div class="td author remote">{{model.remoteUser.name}}</div>
{{/if-eq}}
{{/each}}
I recieved variables like text "model.currentUser.id", using this.get(v1) I can get value.
But this.get working only for model.currentUser.id and don't work for item.record_poster_id (maybe because it's variable from the loop)
QUESION: how i can pass variable by value?
ANSWER: How to compare values in each?
You are passing the variable's value, you're just accessing them incorrectly. Why are you using this.get(v1) to access the argument? Just use v1. It's already the value you passed in, you don't have to do anything special to it.
Also, I'm not sure if that Handlebars syntax will work. Ember might require you to do something like this.
Related
I was using custom Handlebars helper extending the functionality of 'if' block.
In Ember 1.10 this doesnt work anymore as there is no Ember.Handlebars.bind property which allowed binding to the property....
Ember.Handlebars.registerHelper('ifCond', function (a, b, options) {
return Ember.Handlebars.bind.call(options, contexts[0], a, options, true, function(result) {
return result === b
});
});
The usage would be:
{{#ifCond property "value"}}
{{some-other-component}}
{{else}}
something other...
{{/ifCond}}
but this returns an error "Cannot read property 'call' of undefined"
Is there any way that I can bind to passed properties in helper? I cannot use registerBoundHelper because it doesn't support having child blocks...
I wanted to use Component instead of helper but then I cannot use the {{else}} block...
This solution for the helper was previously taken from Logical operator in a handlebars.js {{#if}} conditional
I actually managed to find a way to do it, so I'll write the answer for my own question...
Instead of using undocumented hacks, I used the proposed change: https://github.com/emberjs/ember.js/issues/10295
So my helper looks like this now:
Ember.Handlebars.registerBoundHelper('isSame', function(value1, value2) {
return value1 === value2
});
and the usage:
{{#if (isSame property "value")}}
{{some-other-component}}
{{else if (isSame property "otherValue"}}
something other...
{{else}}
something other...
{{/if}}
I am trying to do what I think should be a very simple task, but have been failing to do so in the past hour. I want to select a select option by default if the user property matches the value.
<select name="myName">
{{#each addKeys myTable}} <!-- addKeys creates variables for keys and values -->
<option value="{{key}}" {{#if currentUser.property === key}}selected="selected"{{/if}}>{{value}}</option>
{{/each}}
</select>
Now I thought this was straightforward enough to be implemented. But it turns out that Spacebars do not allow conditional operators other than the negation exclamation mark, so equal signs are out of question. I then tried something horrible for the sake of trying:
In template myTemplate:
<select name="myName">
{{#each addKeys myTable}}
<option value="{{key}}" {{isSelected currentUser.property key}}>{{value}}</option>
{{/each}}
</select>
In mytemplate.js :
Template.myTemplate.helpers({
isSelected: function(v1, v2) {
if (v1 === v2)
return "selected=\"selected\"";
return '';
}
});
Not only is this code terrible, terrible to look at, it does not work:
Exception in Meteor UI: String contains an invalid character
I don't understand why something that simple seems so impossible to achieve. Am I missing something there?
Here's an overview of {{#if}} statements in Spacebars
Property
Of course the simplest possible implementation is when the scoped object has a property that evaluates to a boolean
For example if you had:
var item = {
text: 'hello',
checked: false
};
Then you could evaluate an if block like this:
class="{{#if checked}}checked{{/if}}"
Function
We could also evaluate a function here as well. Rather than add a function to the item, we can add a function to the helper and it will inherit the datacontext of the item being passed to it. So if we had the following helper:
Template.item.helpers({
saysHi: function() {
return this.text === "hi";
}
});
Then we could run the following code:
<template name="item">
{{text}}
{{#if saysHi}} - Hi Back {{/if}}
</template>
Note: The helper's implementation can access the current data context as this.
Function with Parameters
You can also pass any number of parameters to helper functions like this:
Template: {{frob a b c verily=true}}
Helper Call: frob(a, b, c, Spacebars.kw({verily: true}))
When applied to our if block, we can do the following:
{{#if equals owner currentUser._id}}
<button class="delete">×</button>
{{/if}}
Then add equals to our template helper like this:
Template.item.helpers({
equals: function(v1, v2) {
return (v1 === v2);
}
});
Universal Helpers
Since this is a generic method that could be useful anywhere, we should add it to every template instead of recreating it.
Note: To create a helper that can be used in any template, use Template.registerHelper.
Template.registerHelper('equals',
function(v1, v2) {
return (v1 === v2);
}
);
Here's a working Demo in MeteorPad that includes one of each of the types of IF's constructed here
Try this:
In your template:
<option value={{key}} selected={{isSelected currentUser.property key}}>
Then have your helper return a boolean.
More on the topic here: https://github.com/meteor/meteor/wiki/Using-Blaze#conditional-attributes-with-no-value-eg-checked-selected
Although spacebars does not support equality, this method works to check for equality
you can use something like this
{{#if chkeq variable value}}
example
{{#if chkeq applicationStatus "Draft"}}
at least it worked for me
where chkeq is a global helper,
which goes something like this
chkeq:function(a,b){
if(a==b){
return true;}
else return false;
}
I want to disable an inputfield if a property is false or does not exist. To do this, you should need a reverse binding for the input helper, something like (pseudo code):
{{ input ... disabled=!isNew}}
After reading the docs, I could find nothing about reverse boolean structure.
Should I solve this by using a computed property*, or is there a better way?
*
Something like:
loginFieldDisabled: function() {
return ! this.get('isNew');
}.property('isNew')
For those who came to question by googling, currently you could use the Ember Truth helpers to achieve a solution for this problem:
{{input ... disabled=(not isNew)}}
I can think of two ways that I would do it. First, use a conditional block:
{{#if isNew}}
{{input}}
{{else}}
{{input disabled}}
{{/if}}
But that comes with its own set of issues, since it adds and removes the text field from the DOM. The other way would be to modify Ember.TextField. Here's something that would work (tested in a JSBin):
Ember.TextField.reopen({
notDisabled: function(key, value) {
if (arguments.length > 1) {
this.set('disabled', !value);
}
return !this.get('disabled');
}.property('disabled')
});
Then, in your template:
{{input notDisabled=isNew}}
The second one is probably what you want. You could also extend Ember.TextField instead of modifying it.
I am trying to do something like this:
<a href="#/{{unbound goto}}" {{bind-attr class=":menu-entry-text :nowrap active:selected-menu-entry-text"}} {{bind-attr id="active:active-nav:inactive-nav"}} {{bind-attr data-goto="goto"}}>
But only the first attribute (class) gets set: id and data-goto are not defined. Is it possible to set several attributes with bind-attr in the same element? How?
Yes you can bind several attributes at once by either using multiple bind-attr helpers like in your example, or just putting all the attributes in a single bind-attr helper. You have an issue in your example though, which is why things aren't working as expected.
The "value if true" form that you're using for the class attribute cannot be applied to other types of attributes. All other attributes must be bound to a dynamic property on the controller. For example, if you had a controller that looked like this:
App.MyController = Ember.ObjectController.extend({
myId: function() {
if (this.get("active") === true) {
"active-nav"
} else {
"inactive-nav"
}
}.property("active")
});
Then you would bind that like so:
<a href="#/{{unbound goto}}" {{bind-attr id="myID"}}>
Just a side note on that example, it's probably a code smell if you have a dynamic ID for an HTML element. IDs are supposed to uniquely identify a single element and I wouldn't expect them to change. It seems like a class would be a better fit for this use case.
I have a Handlebars helper that takes a number and returns a class name. I want to run the helper only if foobar exists because it might not exist. My initial attempt was:
{{#each content}}
<div class="other_class {{#if foobar}}{{my_helper foobar}}{{/if}}"></div>
{{/each}}
This doesn't work because metamorph inserts script tag placeholders where the if helper is. My second attempt was:
{{#each content}}
<div class="other_class {{my_helper foobar}}"></div>
{{/each}}
This also doesn't work because when foobar does not exist, the string "foobar" is passed to my_helper.
I know that doing {{unbound foobar}} will render the value without binding it and thus without script tag placeholders. Is there a way to use if in an unbound way?
You could create a computed property and add it to classNameBindings of a view, see http://jsfiddle.net/pangratz666/MvpUZ/:
App.MyView = Ember.View.extend({
classNameBindings: 'omg'.w(),
omg: function(){
var foobar = Ember.getPath(this, 'content.foobar');
return (foobar && foobar === 42) ? 'my-class-name' : null;
}.property('content.foobar')
});
There is a helper for this. It's called unboundIf: see documentation
You can use it like this:
{{#unboundIf "content.shouldDisplayTitle"}}
{{content.title}}
{{/unboundIf}}
The expression is only evaluated once.