Проверьте, находится ли значение в массиве для ng-if внутри ng-repeat

У меня есть цикл ng-repeat, проходящий через список вин, полученных из API. У меня также есть переменная массива, содержащая все идентификаторы вин, которые были добавлены в избранное из базы данных. Я хочу иметь возможность отображать кнопку "Добавить в избранное", если пользователь еще не добавил в список конкретное вино результата. Чтобы сделать это, я подумал, что сделаю что-то вроде:

HTML:

<tr ng-repeat="wine in wines">
    <td>{{$index+1}}</td>
    <td>{{ wine.Name }}</td>
    <td>{{ wine.Appellation.Name }}</td>
    <td>${{ wine.PriceMin }} - ${{ wine.PriceMax }}</td>
    <td>
        <!-- If wine.Id is not yet in the array of all favorite ids, display "Add Button" -->
        <a href="#" class="btn btn-primary btn-dark" ng-click="addToFavorites(wine.Id)" ng-if="favorites.indexOf(wine.Id) !> -1"> Add </a>
        <!-- Else Display Already Added -->
        <span ng-if="favorites.indexOf(wine.Id) > -1">Added</span>
    </td>
</tr>

Вот мой JS:

app.controller("MainController", function($scope, $http){
    $scope.favorites = [];
    var getAllFavorites = function(){
        $http.get("/home/getAllFavoriteIds").success(function(response) {
            angular.forEach(response, function(r) {
                $scope.favorites.push(r);
            });
        });
    };
});

Я новичок в .indexOf(), поэтому я думаю, что это проблема. Но, возможно, я ошибаюсь.

Ответы

Ответ 1

Вы можете использовать angular -фильтр содержит фильтр:

<span ng-if="favorites | contains:wine.Id">Added</span>

или напишите свой собственный фильтр, который делает то же самое:

angular.module('module').filter('contains', function() {
  return function (array, needle) {
    return array.indexOf(needle) >= 0;
  };
});

Ответ 2

Я бы рекомендовал вам переместить эту логику на контроллер, чтобы ваше представление было максимально чистым:

   $scope.isFavorites = function(id) {
       return $scope.favorites.indexOf(id) !== -1;
   }

И ваше мнение должно быть:

<!-- If wine.Id is not yet in the array of all favorite ids, display "Add Button" -->
<a href="#" class="btn btn-primary btn-dark" ng-click="addToFavorites(wine.Id)" ng-if="!isFavorites(wine.Id)">Add</a>
<!-- Else Display Already Added -->
<span ng-if="isFavorites(wine.Id)>Added</span>

Ответ 3

Думаю, вам нужно изменить

favorites.indexOf(wine.Id) !> -1

в

favorites.indexOf(wine.Id) < 0

Ответ 4

favorites.indexOf(wine.Id) !> -1 не выглядит как правильное выражение angular. Обратите внимание, что при наличии выражений в ваших шаблонах допускаются только некоторые базовые условия javascript. См. docs для возможного.

Вместо того, чтобы иметь список всех вин и список с любимыми винами, лучше расширить список со всеми винами с булевым свойством isFavorite. Это также лучше для производительности, так как не нужно искать вино во втором списке на каждой итерации.

В цикле обратного вызова ответа (быстрый и грязный):

var index = $scope.favorites.indexOf(r.id);
if(index > -1) {
  $scope.favorites[index].isFavorite = true;
} // else isFavorite is undefined, which is falsy

Операции массива, подобные этому, можно сделать более элегантно с помощью Underscore или Lodash.

Обратите внимание, что если у вас есть объект с винами (ids как ключ), вина могут быть восстановлены по id вместо поиска по индексу каждый раз. ngRepeat поддерживает объекты, подобные массивам.

В вашем шаблоне:

<!-- If wine.Id is not yet in the array of all favorite ids, display "Add Button" -->
<a href="#" class="btn btn-primary btn-dark" ng-click="addToFavorites(wine.Id)" ng-if="!wine.isFavorite"> Add </a>
<!-- Else Display Already Added -->
<span ng-if="wine.isFavorite">Added</span>

Ответ 5

! > недействителен.! может использоваться только с = или с булевым значением. Используйте

favorites.indexOf(wine.Id) == -1

indexOf возвращает -1, если он не может найти элемент в массиве. Спасибо за исправление. Я застрял! >