Reputation: 57
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
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
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
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