0

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;
        };
    };
})();
1
  • 2
    Your service's FoundItems function returns before the searchResult promise is resolved. Commented Aug 21, 2017 at 22:56

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much it seems to have worked. I tried the $promise thing that you recommended. Althought I end up with the[$promise: f] and I was wondering how you would get the value from it ie the array.
1

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.

1 Comment

when you say return the promise do you mean to the controller or to the service.FoundItems? Sorry I'm still new to all this. Could you possibly show me an example code.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.