ng-repeat not working consistently with arrays of items - javascript

I have two arrays of strings that I want to repeat within my page. Here are the arrays (infoData and modelData) in the debugger:
Screenshot of arrays in Chrome inspector:
Here is my html:
<div ng-repeat="info in pTab.infoData">
<p>{{info}}</p>
</div>
<div ng-repeat="stats in pTab.modelData">
<p>{{stats}}</p>
</div>
However the page only displays the contents of infoData as shown below:
XPE
www.sampleurl.com
Sample summary has nulla quis lorem ut libero malesuada feugiat...
My question is why does this happen and how can I get the elements of the second array to display like the first?
Here is some additional info that may be useful to you. As I was trying out different things this struck me as interesting:
The following HTML:
<div ng-repeat="info in pTab.infoData">
<p>{{pTab.infoData}}</p>
</div>
<div ng-repeat="stats in pTab.modelData">
<p>{{pTab.modelData}}</p>
</div>
displays the infoData array in square brackets as a string 3 times (infoData has a length of 3).While the following HTML:
<div ng-repeat="info in pTab.infoData">
<p>{{pTab.modelData}}</p>
</div>
<div ng-repeat="stats in pTab.modelData">
<p>{{pTab.infoData}}</p>
</div>
displays the modelData array in square brackets as a string 3 times.
Is there something wrong with the <div ng-repeat="stats in pTab.modelData">? Because whatever is in that div never repeats, even if I move that div ahead of the <div ng-repeat="stats in pTab.modelData">
If I'm being unclear or you'd like to see more of the code, please let me know. Thank you very much for your time.

If you look in browser console you can see error like this
Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: stats in pTab.modelData, Duplicate key: string:0.1 mg, Duplicate value: 0.1 mg
So, you have duplicated items in your second array, and for resolve this error should use track by expression, in this case enough $index
<div ng-repeat="stats in pTab.modelData track by $index">
A bit more about it you can see in doc: Tracking and Duplicates
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.pTab = {
modelData: [
'0.1 mg',
'0.1 mg',
'0.1 mg'
]
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller='ctrl'>
<h1>Hello Plunker!</h1>
<div ng-repeat="stats in pTab.modelData track by $index">
<p>{{stats}}</p>
</div>
</div>

Related

Why can't I access sub-elements of an AngularJS controller?

I'm guessing this has probably been answered a million times, but I don't have the right language to describe this particular issue. Essentially I can't do something like $ctrl.thing.subelement. The following works just fine:
<div class="col-md-10" ng-repeat="p in $ctrl.patient">
<!--Body content-->
<p>{{p.name}}</p>
<p>{{p.id}}</p>
</div>
This prints the patient name and id -- the behavior I want -- except I don't have the need for a repeat. I want to be able to reference specific patient elements throughout the page.
Similarly, this will print all the patient's information as JSON plaintext (that's how everything is stored).
<div class="col-md-10">
<!--Body content-->
<p>{{$ctrl.patient}}</p>
</div>
What doesn't work is the following (which is what I really want)
<div class="col-md-10">
<!--Body content-->
<p>{{$ctrl.patient.name}}</p>
<p>{{$ctrl.patient.id}}</p>
</div>
What am I missing here? Why am I able to access $ctrl.patient in a div but not $ctrl.patient.name?
Simple because $ctrl.patient is not an object representing a single patient it is an array of patients – which is why you iterate over it. So you need to know which item in the array you want to access by index and then use:
{{$ctrl.patient[0].name}}
Where 0 is the index of the record you want.

ng-repeat on two (or more) rows

My array:
$scope.data = [1,2,3,4,5,6,7,8,9,10];
My HTML:
<div ng-repeat="item in data track by $index">{{item}}</span>
This will output, as expected: 12345678910.
But I want to display the array over two rows, as in the following sample:
12345 // break here
678910
I run some functions on this array, so I don't want to split the array into two smaller ones, cause that would mean I have to run these other functions twice as often. I have looked into the 'start end' part of ngRepeat, but honestly, I don't understand how it works, thoughts?
Note: this is an ionic application, if that matters.
Edit: I can't get the suggested answers to work, I though I could dumb down my code, and make it work, but no. this is my full html ng-repeat code:
<div class="row">
<div class="col" ng-repeat="item in data track by $index">
{{item}}
<br ng-if="$index == 4">
</div>
</div>
This did not work, how come? Anything with row or col?
You could use ng-if to insert a new line when the $index is equal to 4:
<div class="col">
<span ng-repeat="item in data track by $index">
{{item}}
<br ng-if="$index==4">
</span>
</div>
Here, we also move the ng-repeat to a span element inside the div. This solves any potential issues which may arise from the styling applied to the div.
You could also experiment with item.$middle.
item.$middle: true if the repeated element is between the first and last in the iterator
https://docs.angularjs.org/api/ng/directive/ngRepeat
<div ng-repeat="item in data track by $index">
{{item}} <br ng-if="item.$middle" />
</div>
?

AngularJs Separating Results into Divs by column value

I have been struggling to figure out the logic on how to display my results into separate divs in this case bootstrap col-md-4's. It is for a chat messaging app that i'm attempting to build. There is rooms and messages I want each room to only display it's messages grouped together into divs.
My results($scope.messages) look like:
messages = [
{"room_id":1,"message_id":2,"message_content":"hiiii","message_time":"2015-11-28 23:22:57","user_name":"Aaaa1aa"},
{"room_id":1,"message_id":1,"message_content":"hi there","message_time":"2015-11-28 23:22:40","user_name":"aaaa2aa"},
{"room_id":2,"message_id":3,"message_content":"hyyy","message_time":"2015-11-28 23:23:07","user_name":"Guest"},
{"room_id":2,"message_id":4,"message_content":"aaaaa","message_time":"2015-11-28 23:23:20","user_name":"aaaa2aa"}
];
I want to display each results set grouped by the room_id column so when repeating through the data this set would look like so
<div class="col-md-4"> Room Id - 1
aaaa2aa - hi there
Aaaa1aa - hiiii
</div>
<div class="col-md-4"> Room Id - 2
Guest - hyyy
aaaa2aa - aaaaa
</div>
I thought something like this might work after trying several other options but it is not providing any results.
<div class="col-md-4" ng-repeat="data in messages">
<div ng-repeat="data in data[$index]">
{{data.user_name}}
{{data.message_content}}
</div>
</div>
Thanks for any help.
This is what worked for me, but you must first add the module filter as an dependency:
<div class="col-md-4" ng-repeat="data in messages | groupBy: 'room_id'">
{{data[$index].room_id}}
<div ng-repeat="data in data">
{{data.user_name}}
{{data.message_content}}
</div>
</div>
You can use groupBy to group the results:
(k, v) in messages | groupBy: 'room_id'
Another solution would be to use filter:
<div class="col-md-4" ng-repeat="data in messages | filter: '{'room_id': 2}'"> //show only items with room_id set to 2 and so on
</div>
However, this method will be repetitive and redundant.

AngularJS ng-infinite-scroll not working on a specific container/div

I wrote this code after reading multiple posts about ng-infinite-scroll
<div class="course-enrollment-friends" ng-class="{'friends-paginated':showMoreFriends}">
<div class="row" id="enrollment-friends" ng-show="!noFriends">
<div
infinite-scroll="enrollCtrl.retYearAndSem()"
infinite-scroll-disabled='!{{showMoreFriends}}'
infinite-scroll-parent='true'>
<div class="col-md-2" ng-repeat="friend in friends" style="margin-bottom:10px;">
However this didn't work. So I tried something slightly different
<div class="course-enrollment-friends" ng-class="{'friends-paginated':showMoreFriends}">
<div class="row" id="enrollment-friends" ng-show="!noFriends">
<div
infinite-scroll="enrollCtrl.retYearAndSem()"
infinite-scroll-disabled='!{{showMoreFriends}}'
infinite-scroll-container='.course-enrollment-friends'>
<div class="col-md-2" ng-repeat="friend in friends" style="margin-bottom:10px;">
What am I doing wrong?
From the answer in this thread, it seems you forgot the double quotes:
The value of infinite-scroll-container in this example is
double-quoted class name .content then wrapped by single quotes. If
you read the source, the string value eventually gets fed into
document.querySelector. You can read the documentation on that to see
what value it expects.
Without the double quotes .course-enrollment-friends is passed in as a variable name, not as a string as is required.
So
infinite-scroll-container='".course-enrollment-friends"'
instead of
infinite-scroll-container='.course-enrollment-friends'
Try removing the braces around the value given in infinite-scroll-disabled. Use:
<div
infinite-scroll="enrollCtrl.retYearAndSem()"
infinite-scroll-disabled='!showMoreFriends'
infinite-scroll-container='.course-enrollment-friends'>
instead of :
<div
infinite-scroll="enrollCtrl.retYearAndSem()"
infinite-scroll-disabled='!{{showMoreFriends}}'
infinite-scroll-container='.course-enrollment-friends'>

angular ng-repeat, randomize orderBy

I am trying have my angular ng-repeat randomize the items when they appear. The random function I am currently using is below, however when i use this function I get a infdig, causing all sorts of problems. I dont want to do the randomize in the controller because both of these ng-repeats come from the same entry where there is a url and a name but the entry id is in both instances so it would be easier if I dont have to create separate arrays. So does anyone know of a random filter that can be used for this, that wont give me the infdig problems?
$scope.random = function(){
return 0.5 - Math.random();
};
<div ng-repeat="actor in actors | orderBy:random">
<div class="col-md-2">
<div class='imageDropTo'>
<img class='imageDropTo' src={{actor.url}} data-id= {{actor.id}}>
</div>
</div>
</div>
<div ng-repeat="actor in actors | orderBy:random">
<div class='col-md-2'>
<p id='{{actor.id}}' class='namesToDrag'> {{actor.name}} </p>
</div>
</div>

Categories