How to check if array is empty in handlebar templates?(ember js) - javascript

I have template, which contains simple icon template:
<span class="icon {{unbound pperson.medical.diseases '=' 0 'hidden'}}">
<img class="icon" src="/assets/img/icons/icon.svg
</span>
As can be seen I need a flag to show/display it and I'm using hidden class for it. And I have data-array 'diseases'. So if it's empty I should not display icon, if it's not empty I should display this icon. I tried condition:
{unbound pperson.medical.diseases '=' 0 'hidden'}}
This gives error. I found that it was possible to write ember handle bar function and to use but I would like to find inline approach without creating aditional functions. is it possible?

Seems I found solution. Probably on page load diseaseases didn't exist so I added null-undefined check. not it seems to be working
<span class="icon {{unbound (unless (or null-undefined pperson.medical.disease pperson.medical.diseases.length '=' 0 ) 'hidden')}}">

Ember considers an empty array as falsely. So you should be able to do this:
<span class="icon {{unless pperson.medical.diseases 'hidden'}}">
<img class="icon" src="/assets/img/icons/icon.svg
</span>
Personally I feel that relying on the different truthiness of Handlebars templates compared to regular JavaScript makes the code more difficult to read. And Ember.js may change the template syntax to match JavaScript truthiness more closer. So I would recommend checking the length of the array instead. 0 is considered falsely just as in JavaScript.
<span class="icon {{unless pperson.medical.diseases.length 'hidden'}}">
<img class="icon" src="/assets/img/icons/icon.svg
</span>
The {{unbound}} helper is only needed if you want to prevent your template reflecting changes in application state. {{unbound pperson.medical.diseases}} would cause the user interface not to change if items are added or removed from diseases array. This is nearly never what you want. The official template linting rules forbid usage of {{unbound}} as part of their recommended set.
{{unbound pperson.medical.diseases '=' 0 'hidden'}} is not a valid statement assuming that you haven't overloaded the default {{unbound}} template helper. I assume that you are missing something an {{if}} or {{unless}} condition in that snippet and a custom helper, which supports comparison with pperson.medical.diseases '=' 0.

Related

ng-non-bindable with ng-if in Angular Google Maps

So I read Why is ng-non-bindable required for <ui-gmap-windows> element in Angular Google Maps?
and I get how ng-non-bindable is used in the directive.
My problem is that I'm trying to use ng-if to conditionally reveal some icons in my marker infowindows. ng-if doesn't work with ng-non-bindable, and of course, the info windows don't work without it.
If someone can tell me how to make ng-if work in this situation or give an alternative solution, i'd greatly appreciate it.
<ui-gmap-windows show="show">
<div ng-non-bindable>{{obj.name}}<br>{{distance}} miles
<span class="ion-man" ng-if="obj.men"></span>
<span class="ion-woman" ng-if="obj.women"></span>
<span class="ion-ios-people" ng-if="obj.people"></span>
</div>
</div>
</ui-gmap-windows>
You need to use the templateUrl and templateParameter attributes on the ui-gmap-windows directive. The templateUrl is a property on the object that you're passing in which is a string that is the path to the .html template you want to use. The templateParameter is a property on the object that you are passing which is an object containing the parameters you want passed in. See code below. Also you can reference the docs here: http://angular-ui.github.io/angular-google-maps/#!/api/windows
<ui-gmap-windows idKey="'name'" show="show" templateUrl="'pathToHtmltemplate.html'" templateParameter="'{name: 'name', distance: 1.3, womens_restroom: true}'">
</ui-gmap-windows>
Then in your html template you can use ng-if no problem.
Note you have to reference the object you pass into templateParameter as parameter in the html template so the
pathToHtmlTemplate.html file would look like this
<div>
{{parameter.name}}<br>{{parameter.distance}} miles
<span ng-if="parameter.womens_restroom" class="ion-woman"></span>
</div>
The reason it does not work is because, ng-if (600) has lower priority than ng-non-bindable (1000) and ng-non-bindable is terminal:true so ng-if never compiles due to the terminal nature of ng-non-bindable. You could try using ng-switch (1200) directly on the element with ng-non-bindable though since it has higher priority but not sure if that is applicable in your case if you may have multiple conditions that can be true.
You can as well create your own directive say my-non-bindable anddefine it with configuration, {priority:599, terminal:true} and use it with ng-if say:
.directive('gmapTemplate', function() {
return {
priority: 599,
terminal: true
};
});
and use it with ng-if.
<div gmap-template ng-if="someCond">{{obj.name}}<br>{{distance}} miles
Otherwise you will have to wrap non bindables within element with ng-if
<div ng-if="someCond">
<span ng-non-bindable>{{obj.name}}<br>{{distance}} miles</span>
</div>
angular.module('app', []).directive('gmapNonBindable', function() {
return {
priority: 599,
terminal: true
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div ng-app="app" ng-init="test:123; show:false">
Show-->
<input type="checkbox" ng-model="show" />
<div gmap-Non-Bindable ng-if="show">{{test}}</div>
</div>

Curly braces in ng-repeat - Syntax?

I am trying to filter a JSON list based on one of the contained values. For example, I have JSON objects where they all have name, type, description etc and I am attempting to filter based on the parameter stored in $stateParams (which happens to be type). It works if I hard code the type (e.g. "item in items| filter:{Type:'Grain'}").
Also, I know the value from $stateParams is working as I have it set to the page title. Is there a problem with my below syntax?
<div class="list card">
<div ng-repeat="item in items| filter:{Type:'{{type}}'}">
<a class="item item-icon-left" ng-click="onSelectItemList(item)">
<i class="icon ion-home"></i>
{{item.Name}}
</a>
<div>
Thanks in advance.
Yes, the problem is the filter expects an expression, You should not interpolate ({{) the expression to value.
change
filter:{Type:'{{type}}'}
to
filter:{Type:type}
type is expression evaluated against scope and {{type}} --> Value of expression evaluated against the scope.
Use:
<div ng-repeat="item in items| filter:{Type:type}">
You can't do nested interpolation. Filter is expecting an expression, therefore type is evaluated as is.

I want Handlebar {{#if}} logic inside of a Ember.Handlebars.helper

I am converting someone else's code to Handlebars.js and I'm stuck on converting this tag to its {{#handle-bar}}{{/handle-bar}} counterpart.
The previous coder used an {{#ifCond}} to toggle what 'selected'. This is my component.
{{#dropdown-item }}
{{unbound this.itemName}}
{{/dropdown-item}}
Here is the div i want converted to my component
<div class="dropdownItem" {{bind-attr value=formField_DropdownItemID}}{{#ifCond formField_DropdownItemID value}} selected{{/ifCond}} >
{{unbound this.itemName}}
</div>
My first thought was to just pop the div's logic into the the component, like the next example, but this gave me an error.
{{#dropdown-item bind-attr value=formField_DropdownItemID {{#ifCond formField_DropdownItemID value}} selected{{/ifCond}} }}
{{unbound this.itemName}}
{{/dropdown-item}}
Any suggestions?
You can set those properties to compute. The syntax would be:
{{#dropdown-item selected=computedProperty value=formField_DropdownItemID}}
computedProperty can deal with your conditional logic. The whole idea is to pull that out of handlebars anyways. :)

Trying to set a default background picture using Angular.js

I'm new to Angular.js and I'm running into a problem. I'm using ng-repeat to iterate through a list of news items. Each item has a Title and Body, but will have an optional picture url that will be used as the background.
I can get the news item elements with picture URLs to display when there is a url present. See sample code below.
<li class="news-item col-md-6" ng-repeat="announcement in news.announcements | limitTo:8" ng-style="{'background-image': 'url({{announcement.Url}})'}">
I need to set the announcement.Url value to a default background picture URL when announcement.Url is NULL or Undefined. Not sure how I can go about this.
Any help would be much appreciated.
Thanks!
<li class="news-item col-md-6" ng-repeat="announcement in news.announcements | limitTo:8" ng-style="{'background-image': 'url({{announcement.Url || \'path to default image\'}})'}">
Anything between {{ and }} is an angular expression (similar to javascript itself as far as a beginner is concerned). You can simply include the || operator (a logical OR) and put the path to your default image in a string after that. If announcement.Url is null or undefined then it will be "falsy" and the latter half of the OR conditional will be used.
Edit: Notice that I escaped the string delimiters (\') because they are already nested inside a string that uses those delimiters.

How do I reliably determine if parent template item empty or not in jquery template?

I'm using jQuery templates to build a tree. It works very well so far, but I came across an issue when trying to determine if an item is at the root level or not.
I use a template similar to that of render tree items:
<script id="tree-row-tmpl" type="text/x-jquery-tmpl">
<li>
<div class="row ${NodeType}">
${Name}
</div>
{{if expanded}}
<ul>
{{tmpl($data.chidren || []) "#tree-row-tmpl"}}
</ul>
{{/if}}
</li>
</script>
Now in the link click handler I try to determine root node using:
if($.tmplItem(this).parent)
It turned out the root tmplItem.parent is not null (as I expected), but contains an object with two properties: {data:{}, key:0}.
I see that I can check item.parent.parent or one of the properties which exist in regular tmplItem and missing in the root object. But this seems like a kind of hack for me - I'd prefer finding an "official" way of verifying a tmplItem whether it's empty or valid.

Categories

Resources