ng-repeat on one of two arrays based on condition - angularjs

Say I have
<div ng-if="groupA.length > 0" ng-repeat="element in groupA"> .... </div>
<div ng-if="groupA.length == 0" ng-repeat="element in groupB"> .... </div>
Both divs are exactly the same HTML except for the if conditions and the fact that they repeat on two different groups. Am I able to join them together in one div element? I.e. <div ng-repeat="element in (groupA || groupB)"> ... </div>
I know I can check in the controller to and have a condition there like groupC = groupA.length > 0 ? groupA : groupB and have in the html <div ng-repeat="element in groupC> ... </div> but I was wondering if there's a way to do it on HTML directly?

Should work with ternary operators. Demo: https://plnkr.co/edit/yqrUb2UNAasFs4EKaf0b
<div ng-repeat="element in (groupA.length > 0 ? groupA : groupB)"> .... </div>

you can just add a condition inside the ng-repeat like as
<div ng-repeat="element in (groupA.length > 0 ? groupA : groupB)"> </div>
Hope this will help you

Related

Geting incorrect $index value for parent ng-repeat loop

I have following code and try to use $index in delete function but it gives incorrect value of it.
<li ng-repeat="joinMember in data.teamMember | orderBy:'member.screenName || member.fname' ">
<div class="member-list-img">
<a ng-href="">
<img ng-src="{{joinMember.member.data.image ? (joinMember.member.data.imageType == 'avatar' ? '/public/images/avatars/' + joinMember.member.data.image : '/public/images/' + joinMember.member.data.image) : '/public/images/avatars/avatar-73.png'}}" width="100%" alt="{{joinMember.member.screenName ? joinMember.member.screenName : joinMember.member.fname + ' ' + joinMember.member.lname }}" />
</a>
</div>
<div class="member-list-cont">
<h4>
<a ng-href="#">
{{joinMember.member.screenName ? joinMember.member.screenName : joinMember.member.fname + ' ' + joinMember.member.lname }}
</a>
</h4>
<span>{{joinMember.created | date : "MMMM d, y"}}</span>
</div>
<div ng-if="data.canModify" class="membr-delete">
<a ng-href="">
<i class="fa fa-trash text_link" aria-hidden="true" ng-click="deleteTeamMember($parent.$index, joinMember.id)"></i>
</a>
</div>
</li>
That's because the directive ng-if creates a new scope for itself, when you refer to $parent, it access the immediate $parent's scope, i.e., the inner repeat expression's scope.
So if you want to achieve something you wanted like in the former, you may use this:
<div ng-repeat="i in list">
<div ng-repeat="j in list2">
<div ng-if="1">
({{$parent.$parent.$index}} {{$parent.$index}})
</div>
</div>
</div>
if you have more than one inner directives, you can use ng-init for storing $index in a variable for references in child scopes.
<div ng-repeat="i in list" ng-init="outerIndex=$index">
<div ng-repeat="j in list2" ng-init="innerIndex=$index">
<div ng-if="1">
({{outerIndex}} {{innerIndex}})
</div>
</div>
</div>
So try $parent.$parent.$index in your example and please check understanding the scopes
You are using $parent.$index in a div that have ng-if tag. which delete dom element(div) if condition is fall so that case you will receive incorrect $index value. but with ng-show it only add hide class to that div.
So try to ng-show if it is not important to remove div element instead just hide it.
Note:- You are also using orderBy filter in ng-repeat which will sort in only your DOM so if you will find incorrect object value in your controller.
As you can see in the official documentation of angularjs you should get a zero-based index via $index within a ng-repeat. Try the example by angularjs here. Try to debug data.teamMember in your controller to make sure that this is the correct array you'd like to iterate.

Angularjs ng-repeat iterate by 2

I have a for loop in my MVC application like this
for(var i = 0; i < data.length; i +=2){
<div class='#(i== 0? "item active": "item")'>
<div>
#Html.Raw(data[i].Description)
</div>
<div>
#Html.Raw(data[i + 1].Description)
</div>
</div>
}
I want to convert the above code in angularjs.
Means every loop render the record from current and next array index, say i = 0 then render first and second record detail.
Actually it is big object, for clarity I reduce the code, I want to write the same code in ng-repeat
See the fiddle
I end up with a dirty trick:
<div ng-repeat="item in data"
ng-class="{active: $first}" class="item row"
ng-if='$index % 2 == 0'>
<div class='col-lg-6'>{{ item.a }}</div>
<div class='col-lg-6'>{{ data[$index + 1].a }}</div>
</div>
If $index % 2 == 0 only then render, means 0, 2, 4 .. it work as I want.
See to codepen.
You essentially want something like this:
<div ng-repeat="dataEntry in data" ng-class="{active: $first}" class="item">
<div>{{ dataEntry.Description }}</div>
<div ng-if="!$last">{{ data[$index + 1].Description }}</div>
</div>
Use ng-repeat to loop over your data entries
Use ng-class to only apply 'active' class to the first entry (you have access to $first, $last, $even, and $odd, (which are booleans) inside of an ng-repeat scope)
dataEntry represents each entry for each iteration of your data. Use {{ }} to access and render it's contents
You can use $index + 1 to grab the next entry in the array of entries.
I would assume you know that data in this scenario has to be attached / accessible from your $scope.

Angular limit to first ng-if TRUE item in ng-repeat

Hej, how do I show only the first number that evaluates to true inside ng-repeat?
In my directive (or controller) I have:
ctrl.things = [1,2,3,4,5,6];
and in my html:
<div ng-repeat='thing in ctrl.things' >
<span ng-if="thing>3" ng-show="$first">{{thing}}</span>
</div>
How do I display only 4 as a result?
Please bear in mind that this example is simplified. There is actually an ng-repeat inside ng-repeat and because of that (and other things) there are not many things I co do inside the directive (controller). Many thanks for any solution.
Declare a method in the scope
$scope.getData=function(obj){
return obj > 3;
}
Then add this as filter in div
<div ng-repeat='thing in things | filter : getData' ng-if="$first">
<span >{{thing}}</span>
</div>
JSFIDDLE
If wanna to use this
Try like this
Declare a method in the scope
vm.getData=function(obj){
return obj > 3;
}
Then add this as filter in div
<div ng-repeat='thing in vm.things | filter : vm.getData' ng-if="$first">
<span >{{thing}}</span>
</div>
JSFIDDLE
You should have to create a filter or inline it like this:
<div ng-repeat='thing in ctrl.things' ng-if="thing > 3">
<span ng-if="$first">{{thing}}</span>
</div>
That should work
I think you are looking for this:
//controller
$scope.ctrl={};
$scope.ctrl.things=[{1:false},{2:false},{3:false},{4:true},{5:true}];
$scope.check=function(value){
$scope.count = value === true?($scope.count+1):$scope.count;
return $scope.count ===1 ;
}
//end of controller
HTML
<div ng-repeat='(key,value) in ctrl.things' >
<span ng-if="check(value)">{{key}}</span>
</div>
To show first element if you want to show last item you can put ng-if="$last"

ng-repeat except value 2

I have something like that:
<div ng-repeat="element in data.arrayElement">
<strong>{{element.name}}</strong>
</div>
The previuos collection have 5 elements. Can i iterate the collection except the element that has the value 2?. I don't know, maybe like this
<div ng-repeat="element in data.arrayElement | filter:element.val() !== 2">
<strong>{{element.name}}</strong>
</div>
use ngIf because the
ngIf differs from ngShow and ngHide in that ngIf completely removes and recreates the element in the DOM rather than changing its visibility via the display css property.
<div ng-repeat="element in data.arrayElement" ng-if="element.val !== 2">
Just use a ng-hide on that value:
<div ng-repeat="element in data.arrayElement" ng-hide="element.val == 2">
collect
$scope.data = [
{name:'John', value:'1'},
{name:'Mike', value:'2'},
{name:'Alex', value:'3'}
];
html
<div ng-repeat="element in data | filter:{value:'!2'}">
<strong>{{element.name}}</strong>
</div>

Show only open div with angular if

I'm trying to acheive the same behavior as the spring code below:
<c:forEach items="${data}" var="data" varStatus="contador">
<c:if test="${(contador.count-1)%3==0}">
<div class="conjunto-${conjunto} row"> <!-- Show opening div -->
</c:if>
<!-- Some HTML goes here -->
<c:if test="${((contador.count-1)%3==2)}">
</div>
</c:if>
</c:forEach>
Explaining: I want a new div from class row only after 3 other HTML elements have been added.
I have tried this with ng-if, like this:
<div ng-repeat="data in DATA">
<div class="conjunto-{{$index/3}} row" ng-show="$index % 3 == 0" ng-include="'html.html'">
</div>
<div ng-show="$index % 3 != 0" ng-include="'html.html'">
</div>
</div>
But it obviously doesnt work because only one element with be inside de div.row.
Is there an if-clause with which I could add only the opening div and then close it later?
Thanks in advance.
Ok the best way to do this IMO is 2 fold, in your controller have a method similar to this
$scope.createDataChunks = function() {
var a = $scope.DATA,
retArr = [];
while(a.length) {
retArr.push(a.splice(0,3));
}
return retArr;
}
This would give you an array of arrays, each containing 3 (or less) items in it, you then have this as your markup
<div ng-repeat="data in createDataChunks()">
<div class="conjunto-{{$index/3}} row" ng-show="$index % 3 == 0" ng-include="'html.html'">
<!-- put custom HTML here -->
</div>
</div>
I think that's roughly what you are after?

Resources