1

I'm trying to loop through to get all of theids and names from objects that are in arrays which is in another array. It's giving me 'undefined' even when I try to grab from 1 specific object using:

companies[0][0]['id']

This is my array:

enter image description here

enter image description here

Controller:

app.controller('HomeController', ['$scope', 'companies', function($scope, companies) {

    $scope.companies = companies;
        console.log('companies', $scope.companies);

}]);

And I'm not even sure how to display/access it in HTML using expressions:

<div class="container" ng-controller="HomeController">
    <div ng-repeat="company in companies" class="list">
        <a href="#/{{ company.id }}" class="company-name">
        {{ company.name }}
    </div>
</div>

Updated

Factory:

app.factory('companies', ['$http', function($http) {
    data = [];
    for (let i = 1; i < 11; i++) {
        $http.get('https://examplepage.com/wp-json/wp/v2/categories?per_page=50&page=' + i)
        .then(function(response) {
            data.push(response.data);
            console.log('data', data);
        },
        function(err) {
            return err;
        });
    }
    return data;
}]);
hkhuu
  • 23
  • 1
  • 7

1 Answers1

2

Edit (upon question Update)

Problem

The way the interaction between controller(s) and your factory is designed is brittle and error prone. See your code commented below:

// factory
app.factory('companies', ['$http', function($http) {
    data = [];
    for (let i = 1; i < 11; i++) {
        // you CANNOT control when this is going to return
        $http.get('https://examplepage.com/wp-json/wp/v2/categories?per_page=50&page=' + i)
        .then(function(response) {
            // so this doesn't push to `data` synchronously, this DOES NOT
            // guarantee you when you return data, every response.data will be there
            data.push(response.data);
            console.log('data', data);
        },
        function(err) {
            return err;
        });
    }
    // this will always be returned empty ([], as you initialized it) because
    // the async responses (commented above) haven't arrived when this lint his hit.
    return data;
}]);

// controller
$scope.companies = companies; // so, companies will always be [] (empty array)

Solution

You should strongly consider changing the way you implemented the factory to something like this:

The Idea:

  • Do not call the endpoint x (11) times for getting 550 items (50 * 11 times)
  • Provide a function (getCompanies) in the factory which accepts a itemsPerPage and a page parameter, this way you can get as much items as you want and in the page you want. i.e.: for getting 550 items you should call it: companies.getCompanies(550);
  • From any controller which wants to get the companies call companies.getCompanies

The Code:

// factory
app.factory('companies', ['$http', function($http) {

    function fnGetCompanies(itemsPerPage, page) {
        var ipp = itemsPerPage || 50; // 50 default
        var page = page || 0; // 0 default page
        // return the promise instead of data directly since you cannot return the value directly from an asynchronous call
        return $http
            .get('https://examplepage.com/wp-json/wp/v2/categories?per_page=' + ipp + '&page=' + page)
            .then(
                function(response) {
                    // and then return the data once the promise is resolved
                    return response.data;
                },
                function(err) {
                    return err;
                }
            );
    }
    // provide a `getCompanies` function from this factory
    return {
        getCompanies: fnGetCompanies
    }
}]);

// controller
// get 550 items starting from 0
companies.getCompanies(550, 0).then(function(companies) {
    $scope.companies = companies;
});

Additional notes

Remember You cannot return from an asynchronous call inside a synchronous method


Original Post

You could use Array.prototype.reduce first in order to convert the multi-array structure to a single array like this:

$scope.companies = companies.reduce(function(prevArr, currentArr) { return prevArr.concat(currentArr);}, []);

This converts a structure like this:

[
 [{id: 1, name: 'A'}, {id: 2, name: 'B'}, {id: 3, name: 'C'}],
 [{id: 4, name: 'D'}, {id: 5, name: 'E'}, {id: 6, name: 'F'}]
];

into this:

[{"id": 1,"name": "A"},{"id": 2,"name": "B"},{ "id": 3,"name": "C"},{"id": 4,"name": "D"},{"id": 5,"name": "E"},{"id": 6,"name": "F"}]

Simple demo:

var companies =[
 [{id: 1, name: 'A'}, {id: 2, name: 'B'}, {id: 3, name: 'C'}],
 [{id: 4, name: 'D'}, {id: 5, name: 'E'}, {id: 6, name: 'F'}]
];

console.log(companies.reduce(function(prev, current) { return prev.concat(current);}, []));
lealceldeiro
  • 14,342
  • 6
  • 49
  • 80
  • That makes sense, but when I tried to execute it, I get an empty array when `$scope.companies` is console logged – hkhuu Oct 15 '18 at 19:50
  • @hkhuu then there is another problem, not stated in your original post, dude. By any chance is `$scope.companies = companies;` inside an asynchronous code? – lealceldeiro Oct 15 '18 at 20:14
  • I think it might be. It's pulling from a factory that I have in a separate js file. I've updated my original post with that code. Please take a look when you have a chance, thank you! – hkhuu Oct 16 '18 at 13:11
  • @hkhuu, well....wow... this is a completely different problem...let me see. – lealceldeiro Oct 16 '18 at 13:14
  • 1
    wow thank you so much for the breakdown! I really appreciate it! – hkhuu Oct 16 '18 at 14:19