web-dev-qa-db-fra.com

Ng-repeat sur valeur entière

J'essaie d'utiliser ng-repeat sur un div qui devrait contenir une image d'étoile, chaque tarte dans le JSON a une propriété rating de 1-5, et je veux utiliser cette valeur pour boucler x nombre d'étoiles . J'ai un peu ce fonctionnement, mais il est imparfait que je ne peux pas trier à nouveau le tableau et faire en sorte que les étoiles suivent l'élément correct dans la liste car j'utilise [$index] pour suivre l'itération.

Ma solution est plutôt moche aussi, car je crée des tableaux avec autant d'espaces réservés d'index que la valeur de la propriété rating, puis je les pousse dans un tableau pour boucler le nombre approprié d'images. J'aimerais avoir une solution plus élégante.

Comment résoudre ce problème sans utiliser [$index]?

Extrait du JSON:

{"pies": [
    ...

    {
        "name": "Blueberry pie", 
        "imageUrl": "img/blueberrypie.png", 
        "id": "1",
        "rating": "5", //Ng-repeat depending on this value
        "description": "Blueberry pie is amazing."
    },

    ...
]}

Mon contrôleur:

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);
         })
}]);

La liste qui contient les éléments du gâteau:

<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>

Résultat:

pies list

19
Chrillewoodz

Commander this

<div ng-app='myApp' ng-controller="Main">
  <span ng-repeat="n in range('5')">Start{{$index}} &nbsp;&nbsp;</span>
</div>

$scope.range = function(count){

  var ratings = []; 

  for (var i = 0; i < count; i++) { 
    ratings.Push(i) 
  } 

  return ratings;
}

Changez votre html en suivant

<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>
19
dhavalcengg

J'ai résolu cela de cette manière: "items" est votre tableau d'objets dans la portée $, accédant à la propriété "rating", vous pouvez afficher l'étoile si la valeur est inférieure ou identique par rapport à la propriété "rating".

Dans cet exemple, j'utilise certaines polices d'icônes, mais pour le cas d'une image, c'est la même chose.

<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>

J'ai trouvé une meilleure solution qui résout du tout cette exigence:

https://github.com/fraserxu/ionic-rating

3

Il semble que vous itériez sur le pies et c'est de là que le $index Tire sa valeur. Au lieu de ng-repeat="rating in ratings[$index]", Vous devriez utiliser ng-repeat="rating in range(pie.rating)" De cette façon, la note suivrait votre tarte lors de la commande. Ensuite, vous pouvez supprimer complètement la boucle dans le contrôleur.

Pourriez-vous fournir un peu plus de HTML afin que nous puissions voir d'où vient le $index?

Cordialement, Camusensei

EDIT: Vous êtes en effet en train d'itérer sur pies.pies Dans ng-repeat="pie in pies.pies | filter:query | orderBy:orderProp" Donc ce que j'ai écrit plus tôt devrait fonctionner. Voir ci-dessous pour des changements exhaustifs.

Contrôleur :

$http.get('jsons/pies.json')
     .success(function(data, status) {
        $scope.pies = data;
     })
     .error(function(status) {
        console.log(status);
     })

[~ # ~] html [~ # ~] :

<div ng-repeat="rating in range(pie.rating)" class="rating-box"></div>

EDIT2: Désolé, j'ai oublié la fonction de plage (inspirée de Ariya Hidayat ):

$scope.range = function(count){
    return Array.apply(0, Array(+count));
}
2
Camusensei

Le problème est que ng-repeat ne fonctionne qu'avec des tableaux ou des objets, vous ne pouvez donc pas répéter x fois (alors que x est un nombre)

Une solution pourrait être d'écrire une fonction en JavaScript:

$scope.getNumber = function(num) {
    return (new Array(num));
}

Ensuite, utilisez ce code html pour afficher les étoiles sans $ index:

<div ng-repeat="rating in getNumber(pie.rating)"></div> 
1
Ba5t14n

Dans Angular 1.4+, vous obtenez l'erreur suivante lorsque vous utilisez un tableau vide:

Erreur: [ngRepeat: dupes] Les doublons dans un répéteur ne sont pas autorisés.

Les oeuvres suivantes:

$scope.range = function(count) {
    return Array.apply(0, Array(+count)).map(function(value,index){
        return index;
    });
}

<div ng-app='myApp' ng-controller="Main">
    <span ng-repeat="n in range(5)">Start{{$index}} &nbsp;&nbsp;</span>
</div>
0
will.ogden