No Angular, preciso pesquisar objetos em uma matriz

114

No Angular, tenho no escopo um objeto que retorna muitos objetos. Cada um tem um ID (armazenado em um arquivo simples, sem banco de dados e não consigo utilizá-lo ng-resource)

No meu controlador:

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

Na minha opinião, tenho informações adicionais sobre os peixes ocultos por padrão com o ng-showmore, mas quando clico na guia simples mostrar mais, gostaria de chamar a função showdetails(fish.fish_id). Minha função seria algo como:

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

Agora, na visualização, mais detalhes aparecem. No entanto, depois de pesquisar a documentação, não consigo descobrir como pesquisar esse fisharray.

Então, como faço para consultar a matriz? E no console como eu chamo o debugger para que eu tenha o $scopeobjeto para brincar?

tspore
fonte

Respostas:

95

Eu sei se isso pode te ajudar um pouco.

Aqui está algo que tentei simular para você.

Verifique o jsFiddle;)

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

Criou um filtro que você também pode usar em '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;
  }
});

Uso no controlador:

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

Se houver alguma dúvida, é só me avisar.

migontech
fonte
Como sou novo no angular e javascript, não estou entendendo o significado de '+' na declaração "if (+ input [i] .id == + id) {", por favor, compartilhe suas ideias.
Harshavardhan
Solução perfeita !!
Anil Kumar Ram,
1
Acho que o "+ input [i] .id == + id" garante que você está comparando os números. Assim, você pode passar 1 ou '1' para o filtro $ e ele se comportará exatamente da mesma maneira. Estou usando IDs alfanuméricos, então mudei para "input [i] .id === id"
Axel Zehden
211

Você pode usar o serviço $ filter existente. Eu atualizei o violino acima 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';
     }
 }

A documentação angular está aqui http://docs.angularjs.org/api/ng.filter:filter

Adrian Gunawan
fonte
2
muito útil - À medida que aprendo angular, estou percebendo que preciso parar de pensar nas funções jQuery primeiro (estava tentando fazer com que $ .grep fizesse isso) - em vez disso, usar esse serviço $ filter era exatamente o que eu precisava!
Bobby
2
Melhor resposta, pois não envolve escrever seus próprios filtros.
stevenw00
Você poderia adicionar detalhes o que $scope.selectedé / contém. Fazendo uma rápida pesquisa-on selecionado i encontrado ng-selected/ ngSelected: If the expression is truthy, then special attribute "selected" will be set on the element . Isso é o mesmo? No seu exemplo, o que isso faz? Obrigado
surfmuggle
1
Impressionante !. Torna mais simples. Obrigado
Bharath
2
Não se esqueça de adicionar o serviço $ filter ao seu controlador. ou seja: app.controller ('mainController', ['$ filter', function ($ filter) {// $ filter agora pode ser usado.}]);
Lucas Reppe Welander
22

Para adicionar à resposta de @migontech e também ao endereço dele, o comentário de que você poderia "provavelmente torná-lo mais genérico", aqui está uma maneira de fazer isso. A seguir, você poderá pesquisar por qualquer propriedade:

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

A chamada para filtrar se tornaria:

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

Observe, removi o operador unário (+) para permitir correspondências baseadas em string ...

Herringtown
fonte
considerando que a documentação afirma que este é o único caso de uso para ng-init, eu diria que esta é definitivamente a maneira Angular de fazer isso.
bluehallu de
Exemplo muito fácil de entender e muito útil
rainabba
13

Uma solução suja e fácil pode parecer

$scope.showdetails = function(fish_id) {
    angular.forEach($scope.fish, function(fish, key) {
        fish.more = fish.id == fish_id;
    });
};
Arun P Johny
fonte
5
Por que essa é uma solução suja ?
Trialcoder
5
meu palpite seria porque pode haver, tipo, um bilhão de registros de peixes e estamos apenas repetindo-os um por um
RedactedProfile
6
Haveria ainda mais registros em outros idiomas. Quer dizer, há muitos peixes no C ++. (Oh, cale a boca .. Vou votar em mim mesmo .. !!)
Mike Gledhill
7

Suas soluções são corretas, mas desnecessariamente complicadas. Você pode usar a função de filtro de javascript puro . Este é o seu modelo:

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

E esta é a sua função:

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

Você também pode usar a expressão:

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

Mais sobre esta função: LINK

Michał Jarzyna
fonte
4

Vi este tópico, mas queria pesquisar por IDs que não correspondem à minha pesquisa. Código para fazer isso:

found = $filter('filter')($scope.fish, {id: '!fish_id'}, false);
Ogglas
fonte
Isso funcionou para mim. Simples, elegante e fácil de testar. Obrigado!
Kalpesh Panchal