Handlebars conditionals - if-statement

I was surprised when I read Handlebars won't let you put a conditional with little logic like (If something === 1...) , so I'm really stuck on how to make this a Handlebar template.
if {{price_type}} == 1
Example
else if {{price_type}} == 2
{{min_price}}
else
No price
How is this dealt with in Handlebars? Thanks guys

You can do this by writing your own template helper.
Handlebars.registerHelper('conditionalHelper', function(lValue, rValue, options) {
if (lValue == rValue) {
return options.fn(this);
}
return options.inverse(this);
});
This helper will accept two values 'lValue' and 'rValue' and return true or false depending on whether these values are equal or not. We can use this helper in the example given above as follows-
{{#conditionalHelper price_type 1}}
Example
{{else}}
{{#conditionalHelper price_type 2}}
{{min_price}}
{{else}}
No price
{{/conditionalHelper}}
{{/conditionalHelper}}

The handlebars if-helper only works for boolean values. So when you want to perform conditional operations on them you need to create your own helper.
{{#ifPriceType price_type min_type}}{{/ifPriceType}}
Handlebars.registerHelper("ifPriceType",function(price_type,min_type){
if(price_type==1){ return "Example";}
else if(price_type==2){ return min_type;}
else return "No price";
});

You can even achieve in template itself like below:
if {{price_type}} == 1
Example
else
if {{price_type}} == 2
{{min_price}}
else
No price

Related

Grails render template unit test issue

I've got an action in my controller:
def dirtyMarker() {
render(template: '/layouts/modals/marker/dirtyMarker')
}
and Id like to unit test it. Ive been trying lots of possibilities. This may seem simple, but nothing seems to work (Grails 2.2.3). I know that here, testing might not be important but Ive got lots of other methods that returns a rendered template and I dont know how to implement this test..
seems to me that this should work:
void dirtyMarker() {
controller.metaClass.render = { Map params ->
assert params.template == '/layouts/modals/marker/dirtyMarker'
return 'a'
}
def result = controller.dirtyMarker()
assert result == 'a'
}
You can also mock the template:
void testDirtyMarker() {
views['/layouts/modals/marker/_dirtyMarker.gsp'] = 'mock contents'
controller.dirtyMarker()
assert response.text == 'mock contents'
}
See Testing Template Rendering for details

codeigniter custom form validation wont work

I have a input form and I want to check for some user_name properties. For instance if username is only lowercase with numbers. I am using callback function but given only a simple string such as "a" wont return true .. I really dont understand. What am I doing wrong ??
$this->form_validation->set_rules('user_name','User name','required|callback_validate_user_name');
...
if($this->form_validation->run() !== false){
$data['main_content'] = 'pages/news_page';
$this->load->view('templates/home_body_content', $data);
} else {
echo "Damn!";
}
function validate_user_name($user_name){
if(preg_match('/a/', $user_name) === true){
return true;
}
return false;
}
First, PHP preg_match() returns 1 if the pattern matches given subject [Reference]
So use === 1 or == TRUE instead of === true.
Second, callback function should return FALSE when /a/ pattern is occurred, and return TRUE if not.

Pass variables to ember handlebars

I have an Ember.js ArrayController and some handlebar code that looks like this
<p>{{length}} {{pluralize length "thing"}}</p>
Then I've got a handlebar helper that looks like
Handlebars.registerHelper('pluralize', function(count, str){
debugger;
return (count > 1 ? str+"s" : str);
}
);
When the debugger breaks I observe seeing that count = 'length' not a number like I would expect.
So what gives? What's the correct way to accomplish my obvious task.
Working fiddle here. http://jsfiddle.net/MwTuw/2/
The trick is to use Ember.registerBoundHelper which passes all the relevant data as a final argument to the function.
Ember.Handlebars.registerBoundHelper('pluralize', function (count) {
var options = Array.prototype.pop.call(arguments);
var string = options.data.properties[1];
return (count > 1 ? string+"s" : string);
});
This removes the {{if controller.length}} hack that is required with the other solution and means that adding or removing additional objects will update the value accordingly.
How about this:
Ember.Handlebars.registerHelper('pluralize', function (property, options) {
var count = Ember.Handlebars.get(this, property, options);
var _options = options;
count = parseInt(count, 10); //to be sure ...
if (count > 1) {
_options = _options.concat('s');
}
return new Handlebars.SafeString(_options);
});
EDIT
Here is a working fiddle
EDIT 2
Here is your working updated fiddle
Basically the problem was that the handlebar helper was acting when the controller still had no records, I've added a if helper to the template that listen on the controller.length and fires when it changes and so invoking also the handlebar helper to parse the value.
Hope it helps
Using Ember.registerBoundHelper will make all the key-value pairs in the template available as an hash on the 2nd parameter of the helper:
Handlebars template:
{{orderShow dataOrderBy key1="value1" key2="value2" ... keyN="valueN"}}
Javascript:
Ember.Handlebars.registerBoundHelper('orderShow', function(order, options) {
if(options) {
for(var prop in options.hash) {
alert(prop + '="' + options.hash[prop] + '"')
}
}
return order;
}
This behaviour is described at the end of the following page: http://handlebarsjs.com/expressions.html

angularjs if statements?

So I'm running through the tutorial for AngularJS:
I have an array defined in the controller and i'm returning different points in the array by calling when i'm looping through ng-repeat {{feature.name}} {{feature.description}}
What i don't understand is lets say i have a third point in the array called "importance" and it's a number from 1 to 10. I don't want to display that number in the html but what i do want to do is apply a different color to the feature if that "importance" number in the array is 10 vs 1
so how do i write an if statement to do this:
i.e.
<p style="**insert if statement: {{if feature.importance == 10}} color:red; {{/if}} **">{{feature.description}}</p>
no idea if that's right but that's what i want to do
I do not think there is if statement available.
For your styling purpose, ng-class can be used.
<p ng-class="{important: feature.importance == 10 }">
ng-switch is also convenient.
-- update --
take a look at:
https://stackoverflow.com/a/18021855/1238847
angular1.2.0RC seems to have ng-if support.
Actually there is a ternary operator in Angular 1.2.0.
<p style="{{feature.importance == 10 ? 'color:red' : ''}}">{{feature.description}}</p>
I think the answer needs an update.
Previously you could use ngIf directive from AngularUI project (code here if you still want to download it), bad news is that it's not maintained any more.
The good news is that it has been added to the official AngularJS repo (unstable branch) and soon will be available in the stable one.
<div ng-if="something"> Foo bar </div>
Will not just hide the DIV element, but remove it from DOM as well (when something is falsy).
ng-class is probably the best answer to your issue, but AngularUI has an "if" directive:
http://angular-ui.github.com/
search for:
Remove elements from the DOM completely instead of just hiding it.
I used "ui-if" to decide if I should render a data value as a label or an input, relative to the current month:
<tbody id="allocationTableBody">
<tr ng-repeat="a in data.allocations">
<td>{{a.monthAbrv}}</td>
<td ui-if="$index < currentMonth">{{a.amounts[0]}}</td>
</tr>
</tbody>
In the case where your priority would be a label, you could create a switch filter to use inside of ng-class as shown in a previous SO answer : https://stackoverflow.com/a/8309832/1036025 (for the switch filter code)
<p ng-class="feature.importance|switch:{'Urgent':'red', 'Warning': 'orange', 'Normal': 'green'}">...</p>
You can also try this line of code below
<div class="{{is_foo && foo.bar}}">
which shows foo.bar if is_foo is true.
This first one is a directive that evaluates whether something should be in the DOM only once and adds no watch listeners to the page:
angular.module('setIf',[]).directive('setIf',function () {
return {
transclude: 'element',
priority: 1000,
terminal: true,
restrict: 'A',
compile: function (element, attr, linker) {
return function (scope, iterStartElement, attr) {
if(attr.waitFor) {
var wait = scope.$watch(attr.waitFor,function(nv,ov){
if(nv) {
build();
wait();
}
});
} else {
build();
}
function build() {
iterStartElement[0].doNotMove = true;
var expression = attr.setIf;
var value = scope.$eval(expression);
if (value) {
linker(scope, function (clone) {
iterStartElement.after(clone);
clone.removeAttr('set-if');
clone.removeAttr('wait-for');
});
}
}
};
}
};
});
This second one is a directive that conditionally applies attributes to elements only once without watch listeners:
i.e.
<div set-attr="{ data-id : post.id, data-name : { value : post.name, condition : post.name != 'FOO' } }"></div>
angular.module('setAttr',[]).directive('setAttr', function() {
return {
restrict: 'A',
priority: 100,
link: function(scope,elem,attrs) {
if(attrs.setAttr.indexOf('{') != -1 && attrs.setAttr.indexOf('}') != -1) {
//you could just angular.isObject(scope.$eval(attrs.setAttr)) for the above but I needed it this way
var data = scope.$eval(attrs.setAttr);
angular.forEach(data, function(v,k){
if(angular.isObject(v)) {
if(v.value && v.condition) {
elem.attr(k,v.value);
elem.removeAttr('set-attr');
}
} else {
elem.attr(k,v);
elem.removeAttr('set-attr');
}
});
}
}
}
});
Of course your can use dynamic versions built into angular:
<div ng-class="{ 'myclass' : item.iscool }"></div>
You can also use the new ng-if added by angularjs which basically replaces ui-if created by the angularui team these will conditionally add and remove things from the DOM and add watch listeners to keep evaluating:
<div ng-if="item.iscool"></div>
What also works is:
<span>{{ varWithValue || 'If empty use this string' }}</span>

Check for a value equals to in Ember Handlebar If block helper

How do we check for a value equality in ember.js's If-block helper?
{{#if person=="John"}}
How do we perform above in handlebars?
The {{#if}} helper can only test for properties, not arbitrary expressions. The best thing to do in cases like this is therefore to write a property computing whatever conditional you want to test for.
personIsJohn: function() {
return this.get('person') === 'John';
}.property('person')
Then do {{#if personIsJohn}}.
Note: If you find this too limiting, you can also register your own more powerful if helper.
Use an Ember.Component, thus avoid repetitively defining computed properties in your classes (like personIsJohn above):
// if_equal_component.js script
App.IfEqualComponent = Ember.Component.extend({
isEqual: function() {
return this.get('param1') === this.get('param2');
}.property('param1', 'param2')
});
// if-equal.handlebars template
{{#if isEqual}}
{{yield}}
{{/if}}
You can define the else part of the comparison, with an App.ElseEqualComponent:
// else_equal_component.js script
App.ElseEqualComponent = App.IfEqualComponent.extend();
// else-equal.handlebars template
{{#unless isEqual}}
{{yield}}
{{/unless}}
Usage:
{{#if-equal param1=person param2="John"}}
Hi John!
{{/if-equal}}
{{#else-equal param1=person param2="John"}}
Who are you?
{{/else-equal}}
If you're using HTMLBars (Ember version 1.10+), then you can use the Ember Truth Helper addon:
https://github.com/jmurphyau/ember-truth-helpers
Once installed, it'll be as simple as this:
{{#if (eq person "John")}} hello {{/if}}
although this problem can be solved using eq helper by writing
{{#if (eq person "John")}} hello {{/if}}
but for a general solution you can make your own helper which will take three params param[0] and param[2] being operand and param[1] being operator. Below is the helper file.
compare.js
import Ember from 'ember';
export function compare(params) {
if(params[3]){ //handle case insensitive conditions if 4 param is passed.
params[0]= params[0].toLowerCase();
params[2]= params[2].toLowerCase();
}
let v1 = params[0];
let operator = params[1];
let v2 = params[2];
switch (operator) {
case '==':
return (v1 == v2);
case '!=':
return (v1 != v2);
case '===':
return (v1 === v2);
case '<':
return (v1 < v2);
case '<=':
return (v1 <= v2);
case '>':
return (v1 > v2);
case '>=':
return (v1 >= v2);
case '&&':
return !!(v1 && v2);
case '||':
return !!(v1 || v2);
default:
return false;
}
}
export default Ember.Helper.helper(compare);
now you can easily use it for multiple purpose.
for equality check.
{{#if (compare person '===' 'John')}} {{/if}}
for greater check.
{{#if (compare money '>' 300)}} {{/if}}
and so on.
Expanding on Jo Liss's answer, you can now do this using a computed property macro for more concise and readable code.
personIsJohn: function() {
return this.get('person') === 'John';
}.property('person')
becomes
personIsJohn: Ember.computed.equal('person', 'John')
Relavent Docs.