HandlebarsJS {{#if}} statement inside {{#each}} - backbone.js

I have Backbone App where I use Handlebars to render my data in my HTML files. So, I try to achieve that if a Collection should be empty e.g have no data, there should just be a simple <p>-tag which tells the user that there is currently no data. In this case, if there is a biography available, it should be displayed and if not, a simple text like "there's no biography yet" or something like that. So I tried this:
{{#each this}}
{{#if this}}
<p>{{bio}}</p>
{{else}}
<p>There is no biography yet!</p>
{{/if}}
{{/each}}
but with no luck! How can I achieve this?

give this a try. #unless stands for if not.
{{#each this}}
<p>{{bio}}</p>
{{/each}}
{{#unless this}}
<p>There is no biography yet!</p>
{{/unless}}

Related

How to process an array (or manually process ng-repeat)?

Using: AngularJS v1.3.15
Disclaimer: I know virtually nothing about angularjs. But I'm "forced" to use it because its being used in a framework that I am using.
I want to modify some html/angularjs that looks like this:
<ul>
<li ng-repeat="provider in model.externalProviders">
<a class="pure-button" href="{{provider.href}}">{{provider.text}}</a>
</li>
</ul>
I can see what is going on here... ng-repeat causes an iteration on the elements of the model.externalProviders collection/array. It works fine, but I have no control over content/styling individual <a> elements depending on the provider. I would like to change the content/appearance of the <a> element depending on type.
The relevant part of the model looks like this:
"externalProviders": [
{
"type": "Google",
"text": "Sign-in with Google",
"href": "https://localhost:44302/external?provider=Google&signin=04e029cf1018403f1757b097fbfb1ecb"
}
],
So I thought maybe there is a way to "select" or "pick" from externalProviders by type... If that type exists, then render the appropriate markup, e.g.:
<ul>
<!-- if model.externalProviders has item with type=="Google"... -->
<li>
<a class="pure-button button.google" href="<i class="fab fa-google"></i>{{provider.href}}">{{provider.text}}</a>
</li>
<!-- if model.externalProviders has item with type=="Facebook"... -->
<li>
<a class="pure-button button.facebook" href="<i class="fab fa-facebook"></i>{{provider.href}}">{{provider.text}}</a>
</li>
</ul>
Not sure what the proper search terms would be so I had trouble finding any info that might solve my problem. Is something like this possible with AngularJS? If so, how would I accomplish it?
As #Major Sam commented, the ngClass might work for less simple scenarios, but I don't even need to go that far. Luckily I have control over the type property and the css, so I can make my type and css selector match the font awesome icon class selector for the icon. This works:
<li ng-repeat="provider in model.externalProviders">
<a class="pure-button button-{{provider.type}}" href="{{provider.href}}"><i class="fab fa-{{provider.type}}"></i>{{provider.text}}</a>
</li>
Drawbacks: Doesn't allow you to change the actual markup (like, e.g., not include the icon if font awesome didn't have one for that provider).

Scraping based on "nested property"

After having created a few different spiders I thought I could scrape practically anything, but I've hit a roadblock.
Given the following code snippet:
<div class="col-md-4">
<div class="tab-title">Homepage</div>
<p>
<a target="_blank" rel="nofollow"
href="http://www.bitcoin.org">http://www.bitcoin.org
</a>
</p>
</div>
How would you go about selecting the link that is in within <a ... </a> based on the text within the tab-title div?
The reason that I require that condition is because there are several other links that fit this condition:
response.css('div.col-md-4 a::attr(href)').extract()
My best guess is the following:
response.css('div.col-md-4 div.tab-title:contains("Homepage") a::attr(href)').extract()
Any insights are appreciated! Thank you in advance.
Note: I am using Scrapy.
How about this using XPath:
response.xpath('//div[#class="tab-title" and contains(., "Homepage")]/..//a/#href')
Find a div with class tab-title which contains Homepage inside, then step up to the parent and look for a child on any level.
EDIT:
Using CSS, you should be able to do it like this:
response.css('div.tab-title:contains("Homepage") ~ * a::attr(href)')

show images in disorder by the ng-repeat in angularjs

you can see part of my code:
<ul>
<li ng-repeat="commentItem in comments track by $index">
<div style="float: left; width: 15%;;">
<img width="100%" src="{{commentItem.headImage}}">
</div>
</li>
</ul>
<ion-infinite-scroll ng-if="comment.loadMore" on-infinite="loadMoreComments()">
</ion-infinite-scroll>
when the 'comments' contains less data ,all looks normal.But when there are lots of data in the array(maybe 100 or more),the images will be showed in disorder.For example, the image should be in the third "li" will be showed in the fourth "li".Could anyone tell me why,please!
PS. I use the ionic.bundle.js,but I dont know it will cause something wrong or not. And when the event of ion-infinite-scroll be tiggered,I will push the new data into the "comments" array.
Tracking by $index is not a good idea. Can you track by commentItem.id (or another unique identifier on the commentItem) instead? I'm not sure if that will solve the problem but looking at that code snippet, that's the first thing I would try.

Is there any directive that acts like a "with" in angular?

Say you have an object yourObject on the scope and you want to access some deep properties like the following :
<ol>
<li ng-bind="yourObject.thing.map.one"></li>
<li ng-bind="yourObject.thing.map.two"></li>
<li ng-bind="yourObject.thing.map.three"></li>
</ol>
Is there any built-in directive that could make it look more like this:
<ol ng-with="yourObject.thing.map">
<li ng-bind="one"></li>
<li ng-bind="two"></li>
<li ng-bind="three"></li>
</ol>
UPDATE
A similar question was already. Please see Equivalent of {{#with}} in angular
One way I would do this scenario is by implementing a controller that will have a variables to those an array of one, two three... and then using ng-repeat to loop over that.
So for ng-controller, you could write, ng-controller="SomeCtrl as ctrl"
and then ctrl.arrayVariable would hold an array of all the data you want to show
To make matters very simple, you could use ng-repeat to loop through the data.
So, possibly, ng-repeat="var in ctrl.arrayVariable"
Anyways, I'm not sure exactly how your code is structured, but it should work in most instances.
Long story short, ng-repeat is awesome

Conditionally change img src based on model data

I want to represent model data as different images using Angular but having some trouble finding the "right" way to do it. The Angular API docs on expressions say that conditional expressions are not allowed...
Simplifying a lot, the model data is fetched via AJAX and shows you the status of each interface on a router. Something like:
$scope.interfaces = ["UP", "DOWN", "UP", "UP", "UP", "UP", "DOWN"]
So, in Angular, we can display the state of each interface with something like:
<ul>
<li ng-repeat=interface in interfaces>{{interface}}
</ul>
BUT - Instead of the values from the model, I'd like to show a suitable image. Something following this general idea.
<ul>
<li ng-repeat=interface in interfaces>
{{if interface=="UP"}}
<img src='green-checkmark.png'>
{{else}}
<img src='big-black-X.png'>
{{/if}}
</ul>
(I think Ember supports this type of construct)
Of course, I could modify the controller to return image URLs based on the actual model data but that seems to violate the separation of model and view, no?
This SO Posting suggested using a directive to change the bg-img source. But then we are back to putting URLs in the JS not the template...
All suggestions appreciated. Thanks.
please excuse any typos
Instead of src you need ng-src.
AngularJS views support binary operators
condition && true || false
So your img tag would look like this
<img ng-src="{{interface == 'UP' && 'green-checkmark.png' || 'big-black-X.png'}}"/>
Note : the quotes (ie 'green-checkmark.png') are important here. It won't work without quotes.
plunker here (open dev tools to see the produced HTML)
Another alternative (other than binary operators suggested by #jm-) is to use ng-switch:
<span ng-switch on="interface">
<img ng-switch-when="UP" src='green-checkmark.png'>
<img ng-switch-default src='big-black-X.png'>
</span>
ng-switch will likely be better/easier if you have more than two images.
Another way ..
<img ng-src="{{!video.playing ? 'img/icons/play-rounded-button-outline.svg' : 'img/icons/pause-thin-rounded-button.svg'}}" />
<ul>
<li ng-repeat=interface in interfaces>
<img src='green-checkmark.png' ng-show="interface=='UP'" />
<img src='big-black-X.png' ng-show="interface=='DOWN'" />
</li>
</ul>
For angular 4 I have used
<img [src]="data.pic ? data.pic : 'assets/images/no-image.png' " alt="Image" title="Image">
It works for me , I hope it may use to other's also for Angular 4-5. :)

Resources