Aaron Feigenbaum Aaron Feigenbaum - 6 days ago 7
AngularJS Question

ng-if conflicting with ng-repeat filter?

I have a table that displays city info and starts a new row after every 3 entries. Before I added the ng-if conditions, I was able to filter each entry by city, country and continent. Now, whatever I enter into the input boxes to filter the table only returns the entire first row. What's going on? (Sorry if it's not that readable.)

<table align="center" ng-show="toggleFlag">
<tbody ng-if="$index%3==0" ng-repeat="item in pic|filter:pic.capital|filter:pic.country|filter:pic.continent">
<tr>
<td ng-if="$index<pic.length">
<img ng-src="{{pic[$index].image}}"><br><div>{{pic[$index].capital}} is the capital of {{pic[$index].country}},<br> which is located in {{pic[$index].continent}}.</div>
</td>
<td ng-if="$index<pic.length-1">
<img ng-src="{{pic[$index+1].image}}"><br><div>{{pic[$index+1].capital}} is the capital of {{pic[$index+1].country}}
,<br> which is located in {{pic[$index+1].continent}}.</div>
</td>
<td ng-if="$index<pic.length-2">
<img ng-src="{{pic[$index+2].image}}"><br><div>{{pic[$index+2].capital}} is the capital of {{pic[$index+2].country}},<br> which is located in {{pic[$index+2].continent}}.</div>
</td>
</tr>
</tbody>
</table>


Here are the input boxes:

<h1>City Database Search: <input ng-model="pic.capital"></h1>
<ul><li ng-show="pic.capital" id="li" ng-repeat="item in pic|filter:pic.capital|orderBy:'capital' track by item.capital"><h1>{{item.capital}}</h1></li></ul>
<h1>Country Database Search: <input ng-model="pic.country"></h1>
<ul><li ng-show="pic.country" ng-repeat="item in pic|filter:pic.country|orderBy:'country' track by item.country">
<h1>{{item.country}}</h1></li></ul>
<h1>Continent Database Search: <input ng-model = "pic.continent"></h1>
<ul><li ng-show="pic.continent" ng-repeat="item in pic|filter:pic.continent|orderBy:'continent' track by item.continent">
<h1>{{item.continent}}</h1></li></ul><br>


JSON file:

[
{
"capital":"Ottawa",
"country":"Canada",
"continent":"North America",
"image":"https://upload.wikimedia.org/wikipedia/commons/2/22/Parliament- Ottawa.jpg"
},
{
"capital":"Oslo",
"country":"Norway",
"continent":"Europe",
"image":"https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Downtown_Oslo_Norway_skyline.png/800px-Downtown_Oslo_Norway_skyline.png"
},
{
"capital":"Auckland",
"country":"New Zealand",
"continent":"Oceania",
"image":"https://upload.wikimedia.org/wikipedia/commons/6/6e/Auckland_City_from_Mt_Victoria%2C_Devonport_-_Flickr_-_111_Emergency_%281%29.jpg"
},
{
"capital":"Buenos Aires",
"country":"Argentina",
"continent":"South America",
"image": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c8/Buenos_Aires_Panorama.jpg/800px-Buenos_Aires_Panorama.jpg"
},
{
"capital":"Tokyo",
"country":"Japan",
"continent":"Asia",
"image":"https://upload.wikimedia.org/wikipedia/commons/b/bf/Tokyo_Montage_2015.jpg"
}
]

Answer

Currently, you are voiding the usefulness of the ng-repeat by using the $index to lookup items from pic. Instead, you should use item to refer to the currently iterated item of pic. Similarly, tables for display are generally only useful when a single row is relevant to a single item, otherwise, you should use a different block element to display your items (i have chosen an unordered list).

If i understand your question correctly, it looks like you're trying to add some visual break after every 3rd item. By using the iterator on the list items, and the nth-child selector and the after psuedo-class in css3 we can create a visual break with a little magic.

JSFIDDLE

HTML

<ul id="resultsList">
    <li ng-repeat="item in pic|filter:pic.capital|filter:pic.country|filter:pic.continent">
        <img ng-src="{{item.image}}">
        <br>
        <div>{{item.capital}} is the capital of {{item.country}},
            <br> which is located in {{item.continent}}.
        </div>
    </li>
</ul>

CSS

#resultsList{
    margin:0;
    padding:0;
}
#resultsList li{
    width:33.333%;
    float:left;
    display:block;
    height:200px;
    position:relative;
}
#resultsList li:nth-child(3n+0){
    padding-bottom:20px;
}
#resultsList li:nth-child(3n+0):after{
    content:" ";
    position:absolute;
    left:-200%;
    right:0;
    bottom:0;
    height:20px;
    background: red;
}
#resultsList li img{
    width:100%;
    max-height:150px;
    margin:0 auto;
}
Comments