Using AngularJS how could I randomize the order of a collection?
Solution 1
EDIT Warning!: These results are skewed, don't use this. This answer is only left as a warning until further editing.
Explanation: There should be an equal chance of any item being in the first position, but the actual percent chance after 10,000 iterations of, for example, 6 items, ends up being
1: ~28%, 2: ~10%, 3: ~14%, 4: ~20%, 5: ~12%, 6: ~15%
orderBy
can take a function parameter, just like array.sort
so you can use your HTML above and define a function random
on the scope like:
$scope.random = function(){
return 0.5 - Math.random();
};
This will return a random value sometimes negative, sometimes positive, sometimes 0, which will randomly sort the array.
Solution 2
Doing a quick fiddle sh0ber method seems to work well: http://jsfiddle.net/owenmead/fa4v8/1/
<div ng-controller="MyCtrl">
<p ng-repeat="i in list|orderBy:random">{{i}}</p>
</div>
function MyCtrl($scope) {
$scope.list = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
$scope.random = function() {
return 0.5 - Math.random();
}
}
Angular's orderBy uses JavaScript's sort() on a copy of the list. Looking at another answer, certain browsers are stable in their sort, others are not. Perhaps just test the fiddle in a few browsers and you should be good to go: Array.sort Sorting Stability in Different Browsers
PS. Couldn't comment on sh0ber's answer as I don't have 50 rep
rmontgomery429
Updated on June 29, 2022Comments
-
rmontgomery429 almost 2 years
How would you order a list of items in AngularJS in random order? I was thinking that the built-in
orderBy
filter would work but I'm not sure how without adding some additional data to the model. Something like would be great.item in items | orderBy:random
My next thought was to create a custom filter but I'd prefer to avoid that if there is something better already available.
-
Dogbert almost 11 yearsNot an expert in Angular, but the filter might get evaluated anytime, and would just keep shuffling the items all the time. You might want to add a "random" property to items when they're loaded, and order by that property.
-
Blazemonger about 10 years@Dogbert has the right of it. In current versions of AngularJS, the accepted answer below generates 'infdig' errors in the console, because sorting is repeated until the same order is produced twice. See this question.
-
-
SJuan76 almost 11 yearsBut the value will not be consistent (it means that you may find that sometimes
a<b
andb<a
, in the same ordering). Are you sure this would have no side effects? -
SJuan76 almost 11 yearsReady my original comment. If each comparation is random, you could end with
a<b
,b<c
,a>c
, and you should ensure that the sorting algorithm can handle that (in fact, it would not match the definition oforder
). Dogbert's comment outlines a method for random ordering where the order is random AND consistent across a run. -
Dan almost 11 yearsGlad it worked out for you. You shouldn't need to use parens to invoke it, check the fiddle from @owenmead below.
-
rmontgomery429 almost 11 years@sh0ber You are correct. The correct way to execute the filter is with only the function name without parens. Thanks.
-
Jossef Harush Kadouri over 9 yearsFYI - this is causing
Error: [$rootScope:infdig]
-
David almost 9 yearsfor
Error: [$rootScope:infdig]
this happens in later versions of angular where the digest cycle executes the random function twice and as the results are inconsistent it retries (thus creating an infinite digest cycle or "infdig") -
cchapman about 8 yearsA note on @DavidAnderton's point (which was very helpful). I realized I had two number fields that were being randomized which was throwing the error. I added a
track by model.id
and it is now working great. -
Prateek Choudhury over 7 yearsAlso a point to be noted that this does not work when you use track by $index. Thanks for the solution.
-
phazei about 7 yearsThis is wrong and shouldn't be used as explained in the comments here stackoverflow.com/a/18650169/65985
-
Dan about 4 years@phazei - Thanks. It's true the results are skewed. I will edit this answer, however, it's not nearly as bad as the top voted comment there claims with no evidence. See this example.