В Angular мне нужно искать объекты в массиве


114

В Angular у меня есть объект, который возвращает множество объектов. У каждого есть идентификатор (он хранится в плоском файле, поэтому БД нет, и я, похоже, не могу его использовать ng-resource)

В моем контроллере:

$scope.fish = [
    {category:'freshwater', id:'1', name: 'trout', more:'false'},
    {category:'freshwater', id:'2', name:'bass', more:'false'}
];

На мой взгляд, у меня есть дополнительная информация о рыбе, скрытой по умолчанию с помощью ng-showmore, но когда я нажимаю вкладку «Показать больше», я хочу вызвать эту функцию showdetails(fish.fish_id). Моя функция будет выглядеть примерно так:

$scope.showdetails = function(fish_id) {  
    var fish = $scope.fish.get({id: fish_id});
    fish.more = true;
}

Теперь в представлении появляется больше деталей. Однако после поиска в документации я не могу понять, как искать в этом fishмассиве.

Итак, как мне запросить массив? А в консоли, как мне вызвать отладчик, чтобы у меня был $scopeобъект для игры?

Ответы:


95

Я знаю, может ли это вам немного помочь.

Вот кое-что, что я попытался смоделировать для вас.

Оформить заказ jsFiddle;)

http://jsfiddle.net/migontech/gbW8Z/5/

Создан фильтр, который также можно использовать в 'ng-repeat'

app.filter('getById', function() {
  return function(input, id) {
    var i=0, len=input.length;
    for (; i<len; i++) {
      if (+input[i].id == +id) {
        return input[i];
      }
    }
    return null;
  }
});

Использование в контроллере:

app.controller('SomeController', ['$scope', '$filter', function($scope, $filter) {
     $scope.fish = [{category:'freshwater', id:'1', name: 'trout', more:'false'},  {category:'freshwater', id:'2', name:'bass', more:'false'}]

     $scope.showdetails = function(fish_id){
         var found = $filter('getById')($scope.fish, fish_id);
         console.log(found);
         $scope.selected = JSON.stringify(found);
     }
}]);

Если есть вопросы, просто дайте мне знать.


Поскольку я новичок в angular и javascript, я не понимаю значения '+' в выражении "if (+ input [i] .id == + id) {", не могли бы вы поделиться своими мыслями.
Харшавардхан,

Идеальное решение !!
Анил Кумар Рам

1
Я думаю, что "+ input [i] .id == + id" гарантирует, что вы сравниваете числа. Таким образом, вы можете передать 1 или 1 фильтру $, и он будет вести себя точно так же. Я использую буквенно-цифровые идентификаторы, поэтому я изменил его на «input [i] .id === id»
Axel Zehden

211

Вы можете использовать существующий сервис $ filter. Я обновил скрипку выше http://jsfiddle.net/gbW8Z/12/

 $scope.showdetails = function(fish_id) {
     var found = $filter('filter')($scope.fish, {id: fish_id}, true);
     if (found.length) {
         $scope.selected = JSON.stringify(found[0]);
     } else {
         $scope.selected = 'Not found';
     }
 }

Документация по Angular находится здесь http://docs.angularjs.org/api/ng.filter:filter


2
очень полезно - когда я изучаю angular, я понимаю, что мне нужно сначала перестать думать о функциях jQuery (для этого пытался получить $ .grep) - скорее, использование этой службы $ filter было именно тем, что мне нужно!
Бобби,

2
Лучший ответ, поскольку он не требует написания собственных фильтров.
stevenw00 05

Не могли бы вы добавить подробности, что $scope.selectedесть / содержит. Выполнение Быстрого поиска на выбранном я нашел ng-selected/ ngSelected: If the expression is truthy, then special attribute "selected" will be set on the element . Это то же самое? В вашем примере что он делает? Спасибо
surfmuggle

1
Потрясающие !. Делает это просто. Спасибо
Bharath

2
Не забудьте добавить в свой контроллер службу $ filter. т.е.: app.controller ('mainController', ['$ filter', function ($ filter) {// Теперь можно использовать $ filter.}]);
Лукас Реппе Веландер,

22

Чтобы добавить к ответу @ migontech, а также к его адресу его комментарий, что вы могли бы «возможно сделать его более общим», вот способ сделать это. Приведенное ниже позволит вам искать по любой собственности:

.filter('getByProperty', function() {
    return function(propertyName, propertyValue, collection) {
        var i=0, len=collection.length;
        for (; i<len; i++) {
            if (collection[i][propertyName] == +propertyValue) {
                return collection[i];
            }
        }
        return null;
    }
});

Тогда вызов filter будет выглядеть так:

var found = $filter('getByProperty')('id', fish_id, $scope.fish);

Обратите внимание, я удалил унарный оператор (+), чтобы разрешить совпадения на основе строк ...


учитывая, что в документации указано, что это единственный вариант использования ng-init, я бы сказал, что это определенно способ Angular.
bluehallu

Очень простой для понимания пример и очень полезный
ранабба

13

Грязное и простое решение может выглядеть как

$scope.showdetails = function(fish_id) {
    angular.forEach($scope.fish, function(fish, key) {
        fish.more = fish.id == fish_id;
    });
};

5
Почему это грязное решение?
Trialcoder 01

5
я предполагаю, потому что там может быть около миллиарда рыбных записей, и мы просто просматриваем их одну за другой
RedctedProfile

6
На других языках было бы еще больше записей. Я имею в виду, что в C ++ много рыбы. (Ой, заткнись .. Я пойду и проголосую за себя .. !!)
Майк Гледхилл


7

Ваши решения правильные, но излишне сложные. Вы можете использовать чистую функцию фильтра javascript . Это ваша модель:

     $scope.fishes = [{category:'freshwater', id:'1', name: 'trout', more:'false'},  {category:'freshwater', id:'2', name:'bass', more:'false'}];

И это ваша функция:

     $scope.showdetails = function(fish_id){
         var found = $scope.fishes.filter({id : fish_id});
         return found;
     };

Вы также можете использовать выражение:

     $scope.showdetails = function(fish_id){
         var found = $scope.fishes.filter(function(fish){ return fish.id === fish_id });
         return found;
     };

Подробнее об этой функции: ССЫЛКА


4

Видел эту ветку, но я хотел найти идентификаторы, которые не соответствовали моему поиску. Код для этого:

found = $filter('filter')($scope.fish, {id: '!fish_id'}, false);

Это сработало для меня. Просто, красиво, легко протестировать. Спасибо!
Kalpesh
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.