113

I have a JSON file containing some data I d like to access on my AngularJS website. Now what I want is to get only one object from the array. So I d like for example Item with id 1.

The data looks like this:

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

I'd like to load the data with AngularJS $http functionality like this:

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

which is working. But how can I now get a specific data object (by id) from the array I get from $http.get ?

starball
  • 20,030
  • 7
  • 43
  • 238
mooonli
  • 2,355
  • 4
  • 23
  • 32

17 Answers17

249

Using ES6 solution

For those still reading this answer, if you are using ES6 the find method was added in arrays. So assuming the same collection, the solution'd be:

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

I'd totally go for this solution now, as is less tied to angular or any other framework. Pure Javascript.

Angular solution (old solution)

I aimed to solve this problem by doing the following:

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

A use case example:

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
  • 5,752
  • 3
  • 30
  • 27
  • 1
    Actually, I'd think it does! After fetching the array, you can use the $filter function to filter out the item with the correct id. – flup Jun 24 '14 at 19:39
  • 11
    This should be the accepted answer. I had the same question in my head and this answer is the only one that uses existing AngularJS and isn' reinventing the wheel. And yes, it is working. – Zoran P. Jul 03 '14 at 14:17
  • 4
    +1 for this being the accepted answer. Best solution using angular libraries. – Meki Oct 07 '14 at 10:08
  • A related topic I found useful for running the filter in an expression: http://stackoverflow.com/questions/17793751/how-to-filter-by-object-property-in-angularjs – Aaron Roller Jun 05 '15 at 08:22
  • 1
    Plunker with filter in an expression: http://plnkr.co/edit/yc0uZejGqWTcUVKvI7Tq?p=preview – Aaron Roller Jun 05 '15 at 08:28
  • 4
    Be aware that filters find by case insensitive substrings by default. So (foo.results, {id: 2}) returns [{id: 12}, {id: 2}], {id:222}] but (foo.results, function (d) {return d.id === 2;}) returns [{id: 2}] – Ryan.lay Jul 26 '15 at 04:31
  • Should just do something like this: var object_by_id = $filter('filter')(foo.results, {id: 2 })[0]; - See my answer below. – Tillman32 Jul 31 '15 at 19:18
  • how performant is angular filter compared to underscore solutions – niklas Nov 11 '15 at 10:10
  • What about filtering with two `id`s? I mean the second `id` comes from a nested data of the `json`. – Lekz Flores Jun 06 '16 at 05:41
  • what is the runtime of this? – dukevin Mar 28 '17 at 03:20
26

For anyone looking at this old post, this is the easiest way to do it currently. It only requires an AngularJS $filter. Its like Willemoes answer, but shorter and easier to understand.

{ 
    "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" }

WARNING

As @mpgn says, this doesn't work properly. This will catch more results. Example: when you search 3 this will catch 23 too

Community
  • 1
  • 1
Tillman32
  • 416
  • 4
  • 9
  • 1
    also catch id: 24 12 222 2002 etc – mpgn Sep 22 '16 at 17:33
  • I would think that the `[0]` would cause it to return the first result it finds from the collection, so it would only work if your collection is sorted and the object you're looking for is the first it finds during its iteration. Eg. if there's a id:12 that comes before id: 2, it would return id: 12. – Roddy of the Frozen Peas Nov 08 '17 at 18:22
25

personally i use underscore for this kind of stuff... so

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

then "a" would be the row that you wanted of your array where the id was equal to 2

Jason Boerner
  • 3,338
  • 1
  • 13
  • 4
  • 1
    I **really love** underscore, but, _does it worse having another JavaScript library?_ – genuinefafa Jul 26 '14 at 03:09
  • 8
    Note that `find` can potentially return multiple objects. Since we only want one, we can use `findWhere` which only returns the first occurrence (which we know is the only occurrence), e.g. `a = _.findWhere(results, {id: 2})`. – gregoltsov Sep 18 '14 at 16:47
17

I just want to add something to Willemoes answer. The same code written directly inside the HTML will look like this:

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

Assuming that "results" is a variable of your FooController and you want to display the "name" property of the filtered item.

Community
  • 1
  • 1
Ena
  • 3,481
  • 36
  • 34
  • @Ena-How to check result of filter is not null or undefined ? – Abhijeet Feb 09 '16 at 08:49
  • I used this HTML variant because I was sure a result existed. I tried and if there is no result the console does not give any error, it simply leaves the text blank. If you need to do some logic if no result is found then I think the best way to go is Willemoes answer (js code inside controller). In that example, you should then check in HTML if single_object variable is null or undefined. – Ena Feb 09 '16 at 09:19
  • 2
    {{(FooController.results | filter : {id: 1})[0].name }: true} - if somebody's looking for an exact match – George Sharvadze Apr 25 '16 at 14:19
12

You can use ng-repeat and pick data only if data matches what you are looking for using ng-show for example:

 <div ng-repeat="data in res.results" ng-show="data.id==1">
     {{data.name}}
 </div>    
Srikanth Jeeva
  • 3,005
  • 4
  • 38
  • 58
  • 2
    If your array has more than a trivial number of items, this will create a lot of unnecessary scopes which may slow down your application. – The DIMM Reaper Sep 02 '15 at 18:37
9

You can just loop over your array:

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

If you don't want to write this messy loops, you can consider using underscore.js or Lo-Dash (example in the latter):

var doc_id_2 = _.filter(doc.results, {id: 2})[0]
kamituel
  • 34,606
  • 6
  • 81
  • 98
8

If you want the list of items like city on the basis of state id then use

var state_Id = 5;
var items = ($filter('filter')(citylist, {stateId: state_Id }));
Ali Adravi
  • 21,707
  • 9
  • 87
  • 85
7

Unfortunately (unless I'm mistaken), I think you need to iterate over the results object.

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

At least this way it will break out of the iteration as soon as it finds the correct matching id.

Simon
  • 2,810
  • 2
  • 18
  • 23
  • Why? Do you have anything to back that up? – Simon Oct 25 '13 at 14:27
  • 11
    Well, do you know what..? I just went off to re-read Javascript - the good parts to counter your argument and I _am_ wrong! For all this time I've been doing it wrong! It hasn't caused me any problems though... yet. I've updated my answer. – Simon Oct 25 '13 at 14:34
6

Why complicate the situation? this is simple write some function like this:

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 '';
}

Use Case:

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'));

output:

Result is Bərdə filialı
Musa
  • 2,596
  • 26
  • 25
4

The only way to do this is to iterate over the array. Obviously if you are sure that the results are ordered by id you can do a binary search

Antonio E.
  • 4,381
  • 2
  • 25
  • 35
  • 46
    ... I really hope after reading this answer people don't think it's a good idea to sort an array then do a binary search. Binary search is *clever*, sure, but *only* if the array is already sorted, and in reality is: 1. easy to poorly implement, 2. Harder to read if poorly implemented. – Ben Lesh Oct 25 '13 at 14:51
  • 4
    I would highly appreciate if the downvoters could motivate their decision. – Antonio E. Jan 13 '15 at 13:02
  • 2
    By default javascript Array type has method find(). The find() method returns the value of the first element in the array that satisfies the provided testing function. – abosancic Jul 20 '17 at 13:12
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>

output: Azərbaycan

2

If you can, design your JSON data structure by making use of the array indexes as IDs. You can even "normalize" your JSON arrays as long as you've no problem making use of the array indexes as "primary key" and "foreign key", something like RDBMS. As such, in future, you can even do something like this:

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

This is the solution "By Design". For your case, simply:

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

Of course, if your ID format is something like "XX-0001" of which its array index is 0, then you can either do some string manipulation to map the ID; or else nothing can be done about that except through the iteration approach.

Antonio Ooi
  • 1,601
  • 1
  • 18
  • 32
2

I know I am too late to answer but it's always better to show up rather than not showing up at all :). ES6 way to get it:

$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
  • 3,508
  • 7
  • 40
  • 71
2

The simple way to get (one) element from array by id:

The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.

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

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

you don't need to use filter() and catch first element xx.filter()[0] like in comments above

The same for objects in array

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

Of course if you have multiple id then use filter() method to get all objects. Cheers

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);
abosancic
  • 1,776
  • 1
  • 15
  • 21
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;
        }
        }

    });
});

Not sure if it's really good, but this was helpful for me.. I needed to use $scope to make it work properly.

Jordy
  • 71
  • 1
  • 1
  • 6
0

use $timeout and run a function to search in "results" array

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
  • 141
  • 1
  • 3
0

I would iterate over the results array using an angularjs filter like this:

var foundResultObject = getObjectFromResultsList(results, 1);

function getObjectFromResultsList(results, resultIdToRetrieve) {
        return $filter('filter')(results, { id: resultIdToRetrieve }, true)[0];
    }
abovetempo
  • 140
  • 2
  • 9