I'm trying to use ng-repeat
on a div
which should contain a star image, each pie in the JSON has a rating
property from 1-5, and I want to use this value to loop out x number of stars. I've got this working somewhat but it's flawed in the way that I can't re-sort the array and make the stars follow the correct item in the list since I'm using [$index]
to track the iteration.
My solution is rather ugly as well since I'm creating arrays with as many index placeholders as the value of the rating
property, and then pushing this into an array to loop out the appropriate number of images. I would like to have a more elegant solution.
How should I go about this problem without using [$index]
?
Snippet of the JSON:
{"pies": [
...
{
"name": "Blueberry pie",
"imageUrl": "img/blueberrypie.png",
"id": "1",
"rating": "5", //Ng-repeat depending on this value
"description": "Blueberry pie is amazing."
},
...
]}
My controller:
pieShopApp.controller('shopCtrl', ['$scope', '$http', '$routeParams', function ($scope, $http, $routeParams) {
$scope.pieId = $routeParams.pieId,
$scope.sortingOptions = ['A-Z', 'Rating'],
$scope.sortingValues = ['name', 'rating'],
$scope.ratings = [],
$http.get('jsons/pies.json')
.success(function(data, status) {
$scope.pies = data;
for (i = 0; i < $scope.pies.pies.length; i++) {
switch ($scope.pies.pies[i].rating) {
case "1": $scope.ratings.push(["1"]); break;
case "2": $scope.ratings.push(["1", "2"]); break;
case "3": $scope.ratings.push(["1", "2", "3"]); break;
case "4": $scope.ratings.push(["1", "2", "3", "4"]); break;
case "5": $scope.ratings.push(["1", "2", "3", "4", "5"]); break;
}
}
console.log($scope.ratings);
})
.error(function(status) {
console.log(status);
})
}]);
The list which contains the pie items:
<div id="pie-list-wrapper">
<ul class="nav">
<a href="#/pies/pieid" ng-repeat="pie in pies.pies | filter:query | orderBy:orderProp">
<li class="list-item rounded-corners box-shadow">
<aside>
<img src="{{pie.imageUrl}}" no-repeat alt="Image of the pie">
</aside>
<header>
<h1 ng-bind="pie.name" id="item-name" class="bold-text"></h1>
</header>
<article>
<span ng-bind="pie.description" id="item-desc"></span>
</article>
<footer id="item-rating">
<div ng-repeat="rating in ratings[$index]" class="rating-box"></div> //Contains the stars
</footer>
</li>
</a>
</ul>
</div>
Outcome:
The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.
Solution 1 There are two mistakes in your code: In your table, you have to wrap the properties between {{ and }}, for example {{employee. Fname}} instead of just employee. Fname .
NEST TWO ng-repeatThe first ng-repeat in the tr tag will create the rows and the second one in the td tag will create one column per element in the collection. By using one ng-repeat for the row and an other for the column, the rows and the columns of your table is now driven by a subset.
"track by" tells the angular js that how angular js will track the association between DOM and the model (i.e. collection). Internally angular js uses "track by $id(obj)" for this purpose. You can use track by $index if you do not have a unique identifier.
Checkout this
<div ng-app='myApp' ng-controller="Main">
<span ng-repeat="n in range('5')">Start{{$index}} </span>
</div>
$scope.range = function(count){
var ratings = [];
for (var i = 0; i < count; i++) {
ratings.push(i)
}
return ratings;
}
Change your html to following
<div id="pie-list-wrapper">
<ul class="nav">
<a href="#/pies/pieid" ng-repeat="pie in pies.pies | filter:query | orderBy:orderProp">
<li class="list-item rounded-corners box-shadow">
<aside>
<img src="{{pie.imageUrl}}" no-repeat alt="Image of the pie">
</aside>
<header>
<h1 ng-bind="pie.name" id="item-name" class="bold-text"></h1>
</header>
<article>
<span ng-bind="pie.description" id="item-desc"></span>
</article>
<footer id="item-rating">
<div ng-repeat="start in range(pie.rating)" class="rating-box"></div> //Contains the stars
</footer>
</li>
</a>
</ul>
</div>
I solved this in this way: "items" is your array of objects in the $scope, accesing the property "rating", you can show the star if the value is less or the same comparing to the "rating" property.
In this example I'm using some icon fonts but for the case of an image is the same thing.
<div ng-repeat="item in items">
<div class="item-offers"">
<img ng-src="{{item.image}}">
<div class="item-not-rating">
<i class="icon ion-ios-star icon-rating" ng-if="item.rate >= 1"></i>
<i class="icon ion-ios-star icon-rating" ng-if="item.rate >= 2"></i>
<i class="icon ion-ios-star icon-rating" ng-if="item.rate >= 3"></i>
<i class="icon ion-ios-star icon-rating" ng-if="item.rate >= 4"></i>
<i class="icon ion-ios-star icon-rating" ng-if="item.rate >= 5"></i>
</div>
</div>
</div>
I've found a better solution that solves this requirement at all:
https://github.com/fraserxu/ionic-rating
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With