Luca Ciancanelli
Luca Ciancanelli

Reputation: 57

How to copy Array from Server to existing Array reference

I've been trying to code up a search engine using angular js, but I can't copy one array to another. When I initiate the the code (in the service.FoundItems in the q.all then function) new array(foundArray) shows up as an empty array. I searched up how to copy one array to another and tried that method as you can see, but it isn't working. Please help, here is the code, and thank you.

P.S. if you need the html please tell me.

(function () {
    'use strict';

    angular.module('narrowDownMenuApp', [])
        .controller('narrowItDownController', narrowItDownController)
        .service('MenuSearchService', MenuSearchService)
        .directive('searchResult', searchResultDirective);

    function searchResultDirective() {
        var ddo = {
            templateUrl: 'searchResult.html',
            scope: {
                items: '<'
            },
        };

        return ddo
    }

    narrowItDownController.$inject = ['MenuSearchService'];
    function narrowItDownController(MenuSearchService) {
        var menu = this;
        menu.input = "";
        menu.displayResult = [];
        menu.searchX = function(name) {
            menu.displayResult = MenuSearchService.FoundItems(menu.input, name);
            console.log(menu.displayResult);
        };
    }
    MenuSearchService.$inject = ['$http', '$q'];
    function MenuSearchService($http, $q) {
        var service = this;
        service.getMatchedMenuItems = function(name, searchTerm) {
            var deferred = $q.defer();
            var foundItems = [];
            var result =  $http({
                method: "GET",
                url: ('https://davids-restaurant.herokuapp.com/menu_items.json'),
                params: {
                    category: name
                }
            }).then(function (result) {
                var items = result.data;
                for (var i = 0; i < items.menu_items.length; i++) {
                    if (searchTerm === ""){
                        deferred.reject("Please enter search term");
                        i = items.menu_items.length;
                    }
                    else if (items.menu_items[i].name.toLowerCase().indexOf(searchTerm.toLowerCase()) ==! -1){
                        foundItems.push(items.menu_items[i].name)
                        deferred.resolve(foundItems);
                    }else {
                        console.log("doesn't match search");
                    }
                }
            });

            return deferred.promise;
        };
        service.FoundItems = function (searchTerm, name) {
            var searchResult = service.getMatchedMenuItems(name, searchTerm);
            var foundArray = [];
            $q.all([searchResult])
                .then(function (foundItems) {
                    foundArray = foundItems[0].slice(0);
                    foundArray.reverse();
                })
                .catch(function (errorResponse) {
                    foundArray.push(errorResponse);
                });
            console.log(foundArray);
            return foundArray;
        };
    };
})();

Upvotes: 0

Views: 86

Answers (3)

georgeawg
georgeawg

Reputation: 48968

If the goal of the service.FoundItems function is to return a reference to an array that is later populated with results from the server, use angular.copy to copy the new array from the server to the existing array:

service.FoundItems = function (searchTerm, name) {
    var foundArray = [];
    var searchPromise = service.getMatchedMenuItems(name, searchTerm);
    foundArray.$promise = searchPromise
      .then(function (foundItems) {
        angular.copy(foundItems, foundArray);
        foundArray.reverse();
        return foundArray;
    })
      .catch(function (errorResponse) {
        return $q.reject(errorResponse);
    })
      .finally(function() {
        console.log(foundArray);
    });
    return foundArray;
}; 

I recommend that the promise be attached to the array reference as a property named $promise so that it can be used to chain functions that depend on results from the server.

Frankly I don't recommend designing services that return array references that are later populated with results. If you insist on designing it that way, this is how it is done.


I tried the $promise thing that you recommended. I was wondering how you would get the value from it ie the array.

In the controller, use the .then method of the $promise to see the final value of the array:

narrowItDownController.$inject = ['MenuSearchService'];
function narrowItDownController(MenuSearchService) {
    var menu = this;
    menu.input = "";
    menu.displayResult = [];
    menu.searchX = function(name) {
        menu.displayResult = MenuSearchService.FoundItems(menu.input, name);
        ̶c̶o̶n̶s̶o̶l̶e̶.̶l̶o̶g̶(̶m̶e̶n̶u̶.̶d̶i̶s̶p̶l̶a̶y̶R̶e̶s̶u̶l̶t̶)̶;̶ 

        menu.displayResult.$promise
          .then(function(foundArray) {
            console.log(foundArray);
            console.log(menu.displayResult);
        }).catch(function(errorResponse) {
            console.log("ERROR");
            console.log(errorResponse);
        });
    };
}

To see the final result, the console.log needs to be moved inside the .then block of the promise.

Upvotes: 1

Christopher
Christopher

Reputation: 876

Titus is right. The function always immediately returns the initial value of foundArray which is an empty array. The promise is executed asynchronously so by the time you are trying to change foundArray it is too late. You need to return the promise itself and then using .then() to retrieve the value just like you are currently doing inside the method.

Upvotes: 1

Moritz Kalwa
Moritz Kalwa

Reputation: 64

From just quickly looking at your code I think you made have a simple error in there. Are you sure you want

foundArray = foundItems[0].slice(0);

instead of

foundArray = foundItems.slice(0);

Upvotes: 0

Related Questions