Obtenir un objet spécifique par identifiant à partir d'un tableau d'objets dans AngularJS

111

J'ai un fichier JSON contenant des données auxquelles je souhaite accéder sur mon site Web AngularJS. Maintenant, ce que je veux, c'est obtenir un seul objet du tableau. Je voudrais donc par exemple Item avec id 1.

Les données ressemblent à ceci:

{ "results": [
    {
        "id": 1,
        "name": "Test"
    },
    {
        "id": 2,
        "name": "Beispiel"
    },
    {
        "id": 3,
        "name": "Sample"
    }
] }

J'aimerais charger les données avec la fonctionnalité AngularJS $ http comme celle-ci:

$http.get("data/SampleData.json");

qui fonctionne. Mais comment puis-je maintenant obtenir un objet de données spécifique (par identifiant) à partir du tableau d'où je viens $http.get?

Merci d'avance pour votre aide.

Salue Marc

mooonli
la source
Avez-vous essayé vous-même? Si oui, pouvons-nous voir ce que vous avez proposé?
simonlchilds
1
Eh bien, je n'ai aucune idée de la meilleure façon d'utiliser AngularJS. Ce que je n'aime pas, c'est parcourir le tableau et faire un égal sur l'id. Peut-être existe-t-il un meilleur moyen?
mooonli
Vous devez vous fier aux traits de soulignement ou à des bibliothèques similaires pour un tel traitement. AngularJS est un framework MVVM et peut ne pas avoir d'API pour cela.
Vijay Pande
@marcbaur - vous devez itérer le tableau. Même si vous utilisez un trait de soulignement, ou quelque chose de similaire, ses fonctions, dans les coulisses, ne font qu'itérer.
Adam
1
s'il vous plaît ajouter un code angulaire pour cela
Ankush Kondhalkar

Réponses:

4

La seule façon de procéder est d'itérer sur le tableau. Évidemment, si vous êtes sûr que les résultats sont classés par identifiant, vous pouvez faire une recherche binaire

Antonio E.
la source
46
... J'espère vraiment qu'après avoir lu cette réponse, les gens ne pensent pas que ce soit une bonne idée de trier un tableau puis de faire une recherche binaire. La recherche binaire est intelligente , bien sûr, mais seulement si le tableau est déjà trié, et en réalité: 1. facile à mal implémenter, 2. plus difficile à lire si mal implémenté.
Ben Lesh
4
J'apprécierais beaucoup si les contrevenants pouvaient motiver leur décision.
Antonio E.
1
Par défaut, le type de tableau javascript a la méthode find (). La méthode find () renvoie la valeur du premier élément du tableau qui satisfait la fonction de test fournie.
abosancic le
246

Utilisation de la solution ES6

Pour ceux qui lisent encore cette réponse, si vous utilisez ES6, la findméthode a été ajoutée dans les tableaux. Donc, en supposant la même collection, la solution serait:

const foo = { "results": [
    {
        "id": 12,
        "name": "Test"
    },
    {
        "id": 2,
        "name": "Beispiel"
    },
    {
        "id": 3,
        "name": "Sample"
    }
] };
foo.results.find(item => item.id === 2)

Je choisirais totalement cette solution maintenant, car elle est moins liée à angulaire ou à tout autre cadre. Javascript pur.

Solution angulaire (ancienne solution)

J'ai cherché à résoudre ce problème en procédant comme suit:

$filter('filter')(foo.results, {id: 1})[0];

Un exemple de cas d'utilisation:

app.controller('FooCtrl', ['$filter', function($filter) {
    var foo = { "results": [
        {
            "id": 12,
            "name": "Test"
        },
        {
            "id": 2,
            "name": "Beispiel"
        },
        {
            "id": 3,
            "name": "Sample"
        }
    ] };

    // We filter the array by id, the result is an array
    // so we select the element 0

    single_object = $filter('filter')(foo.results, function (d) {return d.id === 2;})[0];

    // If you want to see the result, just check the log
    console.log(single_object);
}]);

Plunker: http://plnkr.co/edit/5E7FYqNNqDuqFBlyDqRh?p=preview

Willemoes
la source
1
En fait, je pense que oui! Après avoir récupéré le tableau, vous pouvez utiliser la fonction $ filter pour filtrer l'élément avec l'ID correct.
flup
10
Cela devrait être la réponse acceptée. J'avais la même question dans ma tête et cette réponse est la seule qui utilise AngularJS existant et qui ne réinvente pas la roue. Et oui, ça marche.
Zoran P.
4
+1 pour cela étant la réponse acceptée. Meilleure solution utilisant des bibliothèques angulaires.
Meki
1
Plunker avec filtre dans une expression: plnkr.co/edit/yc0uZejGqWTcUVKvI7Tq?p=preview
Aaron Roller
4
Sachez que les filtres trouvent par défaut les sous-chaînes insensibles à la casse. Donc (foo.results, {id: 2}) renvoie [{id: 12}, {id: 2}], {id: 222}] mais (foo.results, function (d) {return d.id == = 2;}) renvoie [{id: 2}]
Ryan.lay le
26

Pour tous ceux qui consultent cet ancien article, c'est le moyen le plus simple de le faire actuellement. Il ne nécessite qu'un AngularJS $filter. C'est comme la réponse de Willemoes, mais plus courte et plus facile à comprendre.

{ 
    "results": [
        {
            "id": 1,
            "name": "Test"
        },
        {
            "id": 2,
            "name": "Beispiel"
        },
        {
            "id": 3,
            "name": "Sample"
        }
    ] 
}

var object_by_id = $filter('filter')(foo.results, {id: 2 })[0];
// Returns { id: 2, name: "Beispiel" }

AVERTISSEMENT

Comme le dit @mpgn, cela ne fonctionne pas correctement . Cela obtiendra plus de résultats. Exemple: lorsque vous recherchez 3, cela attrapera 23 aussi

Tillman32
la source
1
également attraper id: 24
12222
Je pense que cela le [0]ferait renvoyer le premier résultat qu'il trouve dans la collection, donc cela ne fonctionnerait que si votre collection est triée et que l'objet que vous recherchez est le premier qu'il trouve lors de son itération. Par exemple. s'il y a un identifiant: 12 qui précède id: 2, il renverrait id: 12.
Roddy of the Frozen Peas
25

Personnellement, j'utilise un soulignement pour ce genre de choses ... donc

a = _.find(results,function(rw){ return rw.id == 2 });

alors "a" serait la ligne que vous vouliez de votre tableau où l'id était égal à 2

Jason Boerner
la source
1
J'aime vraiment le soulignement, mais est-ce pire d'avoir une autre bibliothèque JavaScript?
Genuinefafa
8
Notez que findpeut potentiellement renvoyer plusieurs objets. Puisque nous n'en voulons qu'une, nous pouvons utiliser findWherequi ne renvoie que la première occurrence (dont nous savons que c'est la seule occurrence), par exemple a = _.findWhere(results, {id: 2}).
gregoltsov
16

Je veux juste ajouter quelque chose à la réponse de Willemoes . Le même code écrit directement dans le HTML ressemblera à ceci:

{{(FooController.results | filter : {id: 1})[0].name }}

En supposant que "results" est une variable de votre FooController et que vous souhaitez afficher la propriété "name" de l'élément filtré.

Ena
la source
@ Ena-Comment vérifier le résultat du filtre n'est pas nul ou indéfini?
Abhijeet
J'ai utilisé cette variante HTML parce que j'étais sûr qu'un résultat existait. J'ai essayé et s'il n'y a pas de résultat la console ne donne aucune erreur, elle laisse simplement le texte vide. Si vous avez besoin de faire de la logique si aucun résultat n'est trouvé, je pense que la meilleure façon de procéder est la réponse de Willemoes (code js à l'intérieur du contrôleur). Dans cet exemple, vous devez ensuite vérifier en HTML si la variable single_object est nulle ou non définie.
Ena
2
{{(FooController.results | filter: {id: 1}) [0] .name}: true} - si quelqu'un cherche une correspondance exacte
George Sharvadze
12

Vous ne pouvez utiliser ng-repeatet sélectionner des données que si les données correspondent à ce que vous recherchez en utilisant ng-show par exemple:

 <div ng-repeat="data in res.results" ng-show="data.id==1">
     {{data.name}}
 </div>    
James Kuta Simiyu
la source
2
Si votre tableau contient plus d'un nombre insignifiant d'éléments, cela créera de nombreuses étendues inutiles qui peuvent ralentir votre application.
The DIMM Reaper
9

Vous pouvez simplement faire une boucle sur votre tableau:

var doc = { /* your json */ };

function getById(arr, id) {
    for (var d = 0, len = arr.length; d < len; d += 1) {
        if (arr[d].id === id) {
            return arr[d];
        }
    }
}

var doc_id_2 = getById(doc.results, 2);

Si vous ne voulez pas écrire ces boucles désordonnées, vous pouvez envisager d'utiliser underscore.js ou Lo-Dash (exemple dans ce dernier):

var doc_id_2 = _.filter(doc.results, {id: 2})[0]
Kamituel
la source
8

Si vous voulez la liste d'éléments comme la ville sur la base de l'identifiant de l'état, utilisez

var state_Id = 5;
var items = ($filter('filter')(citylist, {stateId: state_Id }));
Ali Adravi
la source
7

Malheureusement (sauf erreur de ma part), je pense que vous devez parcourir l'objet de résultats.

for(var i = 0; i < results.length; i += 1){
    var result = results[i];
    if(result.id === id){
        return result;
    }
}

Au moins de cette façon, il sortira de l'itération dès qu'il trouvera l'ID correspondant correct.

simonlchilds
la source
Pourquoi? Avez-vous quelque chose pour étayer cela?
simonlchilds
11
Eh bien, savez-vous quoi ..? Je suis juste parti pour relire Javascript - les bonnes parties pour contrer votre argument et je me trompe! Pendant tout ce temps, je me suis trompé! Cela ne m'a cependant pas posé de problèmes ... pour le moment. J'ai mis à jour ma réponse.
simonlchilds
6

Pourquoi compliquer la situation? c'est simple écrire une fonction comme celle-ci:

function findBySpecField(data, reqField, value, resField) {
    var container = data;
    for (var i = 0; i < container.length; i++) {
        if (container[i][reqField] == value) {
            return(container[i][resField]);
        }
    }
    return '';
}

Cas d'utilisation:

var data=[{
            "id": 502100,
            "name": "Bərdə filialı"
        },
        {
            "id": 502122
            "name": "10 saylı filialı"
        },
        {
            "id": 503176
            "name": "5 sayli filialı"
        }]

console.log('Result is  '+findBySpecField(data,'id','502100','name'));

production:

Result is Bərdə filialı
Musa
la source
4
$scope.olkes = [{'id':11, 'name':'---Zəhmət olmasa seçim edin---'},
                {'id':15, 'name':'Türkyə'},
                {'id':45, 'name':'Azərbaycan'},
                {'id':60, 'name':'Rusya'},
                {'id':64, 'name':'Gürcüstan'},
                {'id':65, 'name':'Qazaxıstan'}];

<span>{{(olkes | filter: {id:45})[0].name}}</span>

sortie: Azərbaycan

Celal Muhtar
la source
2

Si vous le pouvez, concevez votre structure de données JSON en utilisant les index de tableau comme ID. Vous pouvez même "normaliser" vos tableaux JSON tant que vous n'avez aucun problème à utiliser les index de tableau comme "clé primaire" et "clé étrangère", quelque chose comme SGBDR. En tant que tel, à l'avenir, vous pouvez même faire quelque chose comme ceci:

function getParentById(childID) {
var parentObject = parentArray[childArray[childID].parentID];
return parentObject;
}

C'est la solution "By Design" . Pour votre cas, simplement:

var nameToFind = results[idToQuery - 1].name;

Bien sûr, si le format de votre ID est quelque chose comme "XX-0001" dont son index de tableau est 0 , alors vous pouvez soit faire une manipulation de chaîne pour mapper l'ID; ou bien rien ne peut être fait à ce sujet sauf par l'approche itérative.

Antonio Ooi
la source
2

Je sais que je suis trop tard pour répondre, mais il est toujours préférable de me présenter plutôt que de ne pas se présenter du tout :). ES6 façon de l'obtenir:

$http.get("data/SampleData.json").then(response => {
let id = 'xyz';
let item = response.data.results.find(result => result.id === id);
console.log(item); //your desired item
});
Hitesh Kumar
la source
2

Le moyen simple d'obtenir (un) élément du tableau par id:

La méthode find () renvoie la valeur du premier élément du tableau qui satisfait la fonction de test fournie. Sinon, undefined est renvoyé.

function isBigEnough(element) {
    return element >= 15;
}

var integers = [12, 5, 8, 130, 160, 44];
integers.find(isBigEnough); // 130  only one element - first

vous n'avez pas besoin d'utiliser filter () et d'attraper le premier élément xx.filter () [0] comme dans les commentaires ci-dessus

Idem pour les objets en tableau

var foo = {
"results" : [{
    "id" : 1,
    "name" : "Test"
}, {
    "id" : 2,
    "name" : "Beispiel"
}, {
    "id" : 3,
    "name" : "Sample"
}
]};

var secondElement = foo.results.find(function(item){
    return item.id == 2;
});

var json = JSON.stringify(secondElement);
console.log(json);

Bien sûr, si vous avez plusieurs identifiants, utilisez la méthode filter () pour obtenir tous les objets. À votre santé

function isBigEnough(element) {
    return element >= 15;
}

var integers = [12, 5, 8, 130, 160, 44];
integers.find(isBigEnough); // 130  only one element - first

var foo = {
"results" : [{
    "id" : 1,
    "name" : "Test"
}, {
    "id" : 2,
    "name" : "Beispiel"
}, {
    "id" : 3,
    "name" : "Sample"
}
]};

var secondElement = foo.results.find(function(item){
    return item.id == 2;
});

var json = JSON.stringify(secondElement);
console.log(json);

abosancique
la source
0
    projectDetailsController.controller('ProjectDetailsCtrl', function ($scope, $routeParams, $http) {
    $http.get('data/projects.json').success(function(data) {

        $scope.projects = data;
        console.log(data);

        for(var i = 0; i < data.length; i++) {
        $scope.project = data[i];
        if($scope.project.name === $routeParams.projectName) {
            console.log('project-details',$scope.project);
        return $scope.project;
        }
        }

    });
});

Je ne sais pas si c'est vraiment bon, mais cela m'a été utile. J'avais besoin d'utiliser $ scope pour le faire fonctionner correctement.

Jordy
la source
0

utilisez $ timeout et exécutez une fonction pour rechercher dans le tableau "results"

app.controller("Search", function ($scope, $timeout) {
        var foo = { "results": [
          {
             "id": 12,
             "name": "Test"
          },
          {
             "id": 2,
             "name": "Beispiel"
          },
          {
             "id": 3,
            "name": "Sample"
          }
        ] };
        $timeout(function () {
            for (var i = 0; i < foo.results.length; i++) {
                if (foo.results[i].id=== 2) {
                    $scope.name = foo.results[i].name;
                }
            }
        }, 10);

    });
Moein Fazeli
la source
0

Je voudrais parcourir le tableau des résultats en utilisant un filtre angularjs comme celui-ci:

var foundResultObject = getObjectFromResultsList (résultats, 1);

function getObjectFromResultsList(results, resultIdToRetrieve) {
        return $filter('filter')(results, { id: resultIdToRetrieve }, true)[0];
    }
au-dessus du tempo
la source