Using AngularJS service not getting the data - javascript

If i access the link http://localhost/cgi-bin/superCategory.pl?action=GET
I will get this data:
[{"name":"Baby Care","id":"2","image":"/images/categories/baby-care.png"},{"name":" Bread, Bakery & Dairy Products","id":"5","image":"/images/categories/dairy-products.png"},{"name":"Beverages","id":"6","image":"/images/categories/beverages.png"},{"name":"Others","id":"9","image":"/images/categories/others.png"}]
But when i try to get the same data using AngularJS service and controller, I m not getting the data. This is my controller and service code.
sampleApp.factory('SuperCategoryService', ['$http', function ($http){
var req = {
method: 'POST',
url: 'http://localhost/cgi-bin/superCategory.pl',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: { action: 'GET' }
};
return {
GetSuperCategories: function () {
return $http(req).then(
function(response)
{
if (typeof response === 'object')
{
return response;
}
else
{
alert ('wrong');
}
},
function(response) {
alert ('again worng');
// something went wrong
//return $q.reject(response.data);
});
}
};
}]);
sampleApp.controller('SuperCategoryController', function ($scope,SuperCategoryService) {
$scope.SuperCategories = [];
$scope.GetSuperCategories = function() {
SuperCategoryService.GetSuperCategories().then(
function(d) {
alert (d);
if (d !== undefined) {
alert ('in');
console.log(d);
$scope.SuperCategories = d;
}
else {
alert ('undefined data');
}
},
function(response) {
alert ('error worng');
// something went wrong
//return $q.reject(response.data);
});
};
$scope.GetSuperCategories();
});
though code is reaching to alert ('in'), but nothing is getting assigned to variable $scope.SuperCategories;
Can some one help me what i m doing wrong in assignment.

Your service function is doing $http using .then which is nothing but resolving using chain promise you should get explicit data from object you service will return response.data instead of response
GetSuperCategories: function () {
return $http(req).then(
function(response)
{
var data = response.data;
if (typeof data === 'object')
{
return data ;
}
else
{
alert ('wrong');
}
},
function(response) {
alert ('again worng');
// something went wrong
//return $q.reject(response.data);
});
}
};

Related

window.location.replace is always undefined

I have a ajax post that I need to redirect to redirect url on success.
In the browser debugger I do c the correct url but I'm always getting "MYURL/undefined".
$.ajax({
type: 'POST',
url: "/NewsLetter/Create",
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: data,
success: function(result) { //debug >result={urlOne:'https://localhost:7077'}
// alert('Successfully received Data ');
if (result.UrlOne !== undefined) {
window.location.replace(result.UrlOne);
} else {
window.location.replace(result.UrlTwo);
}
console.log(result);
},
error: function(error) {
alert('Failed to receive the Data');
console.log(JSON.stringify(error));
console.log('Failed ');
}
});
In my controller:
if (ModelState.IsValid && isNewUser == null)
{
//remove for clear code
return Json(new { UrlOne = Url.ActionLink("Index","Home")});
}
TempData["ErrorMes"] = "You are allready register";
return Json(new { UrlTwo = Url.ActionLink("_RegNews", "NewsLetter") });
Pass the JsonSerializerOptions as a parameter when creating the Json object to make property's name case-sensitive during deserialization. The JsonSerializerOptions has PropertyNameCaseInsensitive property that by default set to false. This will prevent the Json serializer to change names to be camel-cased.
var options = new System.Text.Json.JsonSerializerOptions();
if (ModelState.IsValid && isNewUser == null)
{
//remove for clear code
return Json(new { UrlOne = Url.ActionLink("Index","Home")}, options);
}
TempData["ErrorMes"] = "You are allready register";
return Json(new { UrlTwo = Url.ActionLink("_RegNews", "NewsLetter") }, options);
JsonSerializerOptions Class
Please check the return json from controller:
You will find that the key is urlOne instead of UrlOne.
Javascript is case sensitive, So you need to change your code like:
if (result.urlOne !== undefined) {
window.location.replace(result.urlOne);
} else {
window.location.replace(result.urlTwo);
}

Response string JavaScript undefined

I have a program written in angularjs. I'm receiving json data from server when online. I'm developing offline mode now..
I have the problem here but i dont know why i cant fix.
I saved json info to localStorage when program to offline get this json string.
service.js - For webservicecall
webServiceCallPost: function(data, action) {
console.log("data "+JSON.stringify(data));
console.log("action "+JSON.stringify(action));
var deferred = $q.defer();
if (navigator.connection.type != "none") {
return $.ajax({
type: "POST",
url: appConst.serviceUrl.service + action,
crossDomain: true,
dataType: "json",
data: data,
timeout: 2000000,
async: true,
success: function(response) {
localStorage.setItem(data + action, JSON.stringify(response));
deferred.resolve();
},
error: function(xhr, ajaxOptions, thrownError) {
$ionicLoading.hide();
if (xhr.status == 0) {
window.plugins.toast.showShortBottom($translate.instant("timedOutError"));
} else if (xhr.status == 404) {
window.plugins.toast.showShortBottom($translate.instant("timedOutError"));
} else {
window.plugins.toast.showShortBottom($translate.instant("timedOutError"));
}
},
beforeSend: function() {},
complete: function() {}
});
} else {
window.plugins.toast.showShortBottom($translate.instant("checkNetWorkConnection"));
$ionicLoading.hide();
var response1 = JSON.parse(JSON.stringify(localStorage.getItem(data + action)));
return $http.get('').then(function(response) {
return response1;
});
}
}
Controller.js - Retriveing response.
Services.webServiceCallPost('', appConst.services.get_menu_card).then(function(response) {
$ionicLoading.hide();
console.log("Response: " + JSON.stringify(response));
if (response[1].response.status == 1) {
if (response[0].data.menu.length > 0) {
var categoryResponse = [];
angular.forEach(response[0].data.menu, function(value, key) {
if (value.menu_image_name != '') {
var extraData = {
imageUrl: appConst.serviceUrl.menu_image_url + value.menu_image_name
}
}
else {
var extraData = {
imageUrl: 'img/screen.png'
};
}
angular.extend(value, extraData);
categoryResponse.push(value);
});
$rootScope.categories = globalMethods.getDashboardGridView(categoryResponse, 2);
}
if (response[0].data.addons.length > 0) {
$rootScope.totalAddons = [];
angular.forEach(response[0].data.addons, function(value, key) {
var extraData = {
"finalCost": value.price,
"quantity": 1,
imageUrl: appConst.serviceUrl.addon_image_url + value.addon_image
};
angular.extend(value, extraData);
$rootScope.totalAddons.push(value);
});
}
$scope.getSiteSettings();
}
$rootScope.dashboardHistoryId = $ionicHistory.currentHistoryId();
});
Console Output :
When i check from json pretty print its looking same.
Online Response : https://codepaste.net/op0boq
Cached Response : https://codepaste.net/y3bkd6
Problem:
TypeError: Cannot read property 'status' of undefined
When i want to get response1.response.status ok is getting.
But when i'm offline and i get cachedResponse1.response.status its retriving status is undefined. But exactly same data, why ?
if this code
var cachedResponse = JSON.parse(JSON.stringify(localStorage.getItem('' + appConst.services.get_menu_card)));
uses an asynchronous call
console.log("Cached Response: " + cachedResponse);
won't wait for it to finish and would print undefined
Thanks for answer to #PatrickEvans
Then you might have not returned the right thing... but also you shouldn't be doing JSON.parse(JSON.stringify(localStorage.getItem()) it should just be JSON.parse(localStorage.getItem()) localStorage items are already strings, stringifying it is going to mess up what you are trying to do
and
return $q.when(response1);

AngularJS handle calling promise multiple times with some exceptions

I asked this question before (AngularJS handle calling promise multiple times) and now I have different obstacle. Now I have to get cities list but there is an exception.
Cities can be called multiple times like countries (in my old question) and I have to cache data to prevent multiple calls for same data(cities). Old question's solution can block multiple calls but now I have to let some calls (for new country's cities).
So my question is:
How can I cache cities data to prevent call for same data?
(My function have to catch if call is for new country's cities list or not. if yes: call service and get cities, if not: return cities from cache)
Here is my service:
var cityCache = {};
vm.getCities = function (countryCode) {
if (countryCode!=undefined && !cityCache[countryCode]) {
vm.cityPromise = $http({
method: 'POST',
cache: true,
url: API + '/api/Global/CountryCities',
data: {
"CountryCode": countryCode
}
}).then(function successCallback(response,countryCode) {
if (errorHandler(response.data)) {
console.log("cities come from ajax")
cityCache[response.config.data.CountryCode] = response.data;
console.log(cityCache)
return response.data
}
});
} else {
vm.cityPromise = $timeout(function () {//I use this to get promise object
return cityCache[countryCode]
}, 0)
console.log("cities comes from cache");
}
return vm.cityPromise;
}
Example:
Let's say I am calling getCities function 3 times in the same time. I am watching my network traffic via chrome. I see 3 ajax calls. It's normal. But sometimes, I call for same city. I need to edit my function that can understand if city data is already called before (kind of cache). For example: If i ask function 3 times with this arguments:
1-Give me the cities in Germany,
2-Give me the cities in Ireland,
3-Give me the cities in Germany (again),
It's calling 3 times. But I want 1 call for Germany, 1 call for Ireland. Just 2 calls.
Same answer as your other question, just map to country code to the promise.
Also same as before, consider the error case.
var vm = this;
vm.cityPromises = {};
function getCities(countryCode) {
if (!vm.cityPromises[countryCode]) {
vm.cityPromises[countryCode] = $http({
method: 'POST',
cache: true,
url: API + '/api/Global/Countries',
}).then(function successCallback(response) {
if (errorHandler(response.data)) {
console.log("ajax")
return response.data;
}
});
} else {
console.log("cache")
}
return vm.cityPromises[countryCode];
}
You can use your own promise here. Don't forget injecting the $q service.
var cityCache = {};
vm.getCities = function (countryCode) {
var deferred = $q.defer();
if (countryCode!=undefined && !cityCache[countryCode]) {
vm.cityPromise = $http({
method: 'POST',
cache: true,
url: API + '/api/Global/CountryCities',
data: {
"CountryCode": countryCode
}
}).then(function successCallback(response,countryCode) {
if (errorHandler(response.data)) {
cityCache[response.config.data.CountryCode] = response.data;
deferred.resolve(response.data);
}
else{
deferred.reject();
}
});
}
else {
vm.cityPromise = $timeout(function () {//I use this to get promise object
deferred.resolve(cityCache[countryCode]);
}, 0);
}
return deferred.promise;
}
Try to use the $q service from angular:
updated to prevent multiple call of same city:
FIDDLE
the service:
.service("cityService", function($http, $q, $httpParamSerializerJQLike){
//var callCache = {};
var cityCache = {};
return {
getCities: function(countryCode){
//if(callCache[countryCode] === undefined){
var promise = $q.defer();
// callCache[countryCode] = promise;
//}else{
// console.log("return cached promise!!", callCache[countryCode]);
// return callCache[countryCode].promise;
//}
if (countryCode!=undefined && !cityCache[countryCode]) {
console.log("new city");
var data = $httpParamSerializerJQLike({
json: JSON.stringify({
name: countryCode+Math.random().toString(36).substring(7)
})
});
$http({
method: 'POST',
url:"/echo/json/",
data: data
}).then(function(risp) {
console.log("servicelog",risp.data);
cityCache[countryCode] = risp.data;
var obj = angular.extend({cache: false}, risp.data);
promise.resolve(obj);
//callCache[countryCode].resolve(obj);
//delete callCache[countryCode];
});
}else{
setTimeout(function(){
var obj = angular.extend({cache: true}, cityCache[countryCode]);
promise.resolve(obj);
//callCache[countryCode].resolve(obj)
//delete callCache[countryCode];
}, 1000)
}
return promise.promise;
}
}
});
I solved my problem by creating an object for the promise and many thanks to #Luke Harper for helping me before and now :) His answer is also correct but I must add a bit more code for my app.
If you see any problem in my code, please write to me so that I would edit the answer
So here is my solution:
vm.cityPromise = {};
vm.getCities = function (countryCode) {
vm.cityPromise["cityCache"] = countryCode;
if (!vm.cityPromise[countryCode]) {
if (countryCode != undefined && !cityCache[countryCode]) {
vm.cityPromise[countryCode] = $http({
method: 'POST',
cache: true,
url: API + '/api/Global/CountryCities',
data: {
"CountryCode": countryCode
}
}).then(function successCallback(response, countryCode) {
if (errorHandler(response.data)) {
cityCache[response.config.data.CountryCode] = response.data;
console.log("cities ajax, cityCache", cityCache)
return response.data
}
},function error (response){
console.log ("error:",response)
});
} else {
vm.cityPromise[countryCode] = $timeout(function () {
return cityCache[countryCode]
}, 0)
console.log("getCities cache");
}
}
return vm.cityPromise[countryCode];
}

$q promise with foreach

I am writing an angular service to work with SharePoint data and I have run into a problem. I have a function in my service that updates and single item and returns an $http promise which works fine. The problem is I am trying to write a function now that utilizes the first function to loop and update multiple items. I want it to return a single promise once all items have been updated and it should reject if any of the items being updated failed. Here is the function:
this.UpdateListItems = function (webUrl, listName, itemsJson) {
if (numItems == -1) {
numItems = itemsJson.length;
c = 0;
f = 0;
}
var promises = [];
itemsJson.forEach(function (itemProps) {
var itemPromise = this.UpdateListItem(webUrl, listName, itemProps.Id, itemProps)
.then(function (response) {
c++;
if (c == numItems && f == 0) {
numItems = -1;
return itemsJson[listName];
}
}, function (error) {
c++; f++;
alert("ERROR!");//This gets called first alert below
if (c == numItems) {
numItems = -1;
return $q.reject(error);
}
});
promises.push(itemPromise.$promise)
}, this);
return $q.all(promises)
.then(function (data) {
alert("IN SUCCESS"); //This always gets called immediately after first item success instead of waiting for all items to finish
}, function (error) {
alert("IN ERROR"); //This never gets called
});
};
The $q.all is returning immediately after the first item returns successfully instead of waiting for the rest of the async item calls. Any help is much appreciated, I am new to all this. Thanks!
EDIT: Adding UpdateListItem code as requested:
this.UpdateListItem = function (webUrl, listName, itemId, itemProperties) {
if (typeof lists[listName] === 'undefined') {
lists[listName] = [];
}
var post = angular.copy(itemProperties);
DataUtilitySvc.ConvertDatesJson(post);
return this.GetListItemById(webUrl, listName, itemId)
.then(function (item) {
return $http({
url: item.__metadata.uri,
method: 'POST',
contentType: 'application/json',
processData: false,
headers: {
"Accept": "application/json;odata=verbose",
"X-HTTP-Method": "MERGE",
"If-Match": item.__metadata.etag
},
data: JSON.stringify(post),
dataType: "json",
}).then(function (response) {
var temp = [];
temp.push(itemProperties);
DataUtilitySvc.MergeByProperty(lists[listName], temp, 'Id');
return response;
}, function (error) {
return $q.reject(error);
});
}, function (error) {
return $q.reject(error);
});
};
Seems like this.UpdateListItem function already returned promise by having $promise object. That's why you were able to have .then(chain promise) function over it.
So basically you just need to push returned itemPromise object instead of having itemPromise.$promise inside promises array. Basically when you are doing $promise, it creates an array of [undefined, undefined, ...] and will resolve as soon as for loop completed.
Change to
promises.push(itemPromise)
from
promises.push(itemPromise.$promise)
Somewhat this question can relate to this answer

AngularJS typeahead throws 'undefined' is not an object (evaluating 'c.length')

I have been struggling with this for the past one day and even though it seems that everybody has this working, I keep getting this error:
Error: 'undefined' is not an object (evaluating 'c.length')
The following is my html:
<input ng-model="customerQuery"
type="text"
typeahead="suggestion for suggestion in searchCustomers($viewValue)"
typeahead-editable="false"
typeahead-on-select="addCustomerToInvoice($item)"
typeahead-min-length="3"
class="form-control"/>
here is my service:
getCustomers: function(formData) {
return $http({
url: '/api/sales/searchCustomer',
data: {name: formData},
method: 'POST',
header: {'Content-Type':'application/json'}
});
}
and finally here is my controller:
$scope.searchCustomers = function(customer) {
SalesService.getCustomers(customer)
.then(
function(response) {
if (response.data.message) {
console.log(response.data.message);
}
else {
return limitToFilter(response.data, 10);
}
},
function(response) {
console.log(response.data);
}
);
};
Thank you in advance
Hard to say for sure without a running reproduce scenario but one thing that is obviously wrong is that you are not returning results of your service call from the searchCustomers in your controller. It should go something like:
$scope.searchCustomers = function(customer) {
return SalesService.getCustomers(customer)
.then(
function(response) {
if (response.data.message) {
console.log(response.data.message);
}
else {
return limitToFilter(response.data, 10);
}
},
function(response) {
console.log(response.data);
}
);
};
There might be more to it than just this omission so send a reproduce scenario if there are any remaining issues after this fix.

Categories