Extracting json array from http response - javascript

I'm new to AngularJS for a project and I'm trying to extract a json array from a http response to use in a list.
The response looks like this:
{
"DFH0XCMNOperationResponse": {
"ca_return_code": 0,
"ca_inquire_request": {
"ca_last_item_ref": 150,
"ca_item_count": 15,
"ca_cat_item": [
{
"ca_cost": "002.90",
"in_stock": 119,
"ca_description": "Ball Pens Black 24pk",
"on_order": 0,
"ca_department": 10,
"ca_item_ref": 10
},
{
"ca_cost": "002.90",
"in_stock": 6,
"ca_description": "Ball Pens Blue 24pk",
"on_order": 50,
"ca_department": 10,
"ca_item_ref": 20
}
],
"ca_list_start_ref": 0
},
"ca_response_message": "+15 ITEMS RETURNED",
"ca_request_id": "01INQC"
}
}
The code for the resource and request looks like this:
.factory('getCatalog', ['$resource', function($resource){
return $resource('catalogmanagertest/v1/apps/bca45894-92f7-49dc-ae54-b23b89ab6c73/catalog', {}, {query: {method:'POST'}});
}]);
And the controller code relevant looks like this:
angular
.module('catalogController', ['ngMaterial', 'ngResource'])
.controller('catalogController', ['$scope', 'getCatalog', 'catalog', function($scope, getCatalog, catalog) {
$scope.debug = getCatalog.query(); // set scope catalog to array from zOS
$scope.catalog = catalog.ca_cat_item;
$scope.message = "This is a test order message";
this.tiles = buildGridModel({
icon : "avatar:svg-",
title: "",
cost: "€",
background: "",
stock: ""
});
function buildGridModel(tileTmpl){
var it, results = [ ];
var tmp = $scope.debug.DFH0XCMNOperationResponse.ca_inquire_request.ca_cat_item;
console.log(tmp);
The next to last line is what I'm having trouble with. How do extract the expected array? I get the newbie error when I do the console.log:
TypeError: Cannot read property 'ca_inquire_request' of undefined

Replace
$scope.debug = getCatalog.query();
with
getCatalog.query().$promise.then(function (result) {
$scope.debug = result;
console.log($scope.debug.DFH0XCMNOperationResponse.ca_inquire_request.ca_cat_item);
});
Here You can see I just converted api call into the promise.In your code before console is logging variable before response come.

Related

Can print out an object, but cannot access its values in JS

I know this will be a very stupid question, but I've been pulling my hair out trying to figure this out. I'm getting the following response back from an API I'm using:
{
"item_id": "51c3d78797c3e6d8d3b546cf",
"item_name": "Cola, Cherry",
"brand_id": "51db3801176fe9790a89ae0b",
"brand_name": "Coke",
"item_description": "Cherry",
"updated_at": "2013-07-09T00:00:46.000Z",
"nf_ingredient_statement": "Carbonated Water, High Fructose Corn Syrup and/or Sucrose, Caramel Color, Phosphoric Acid, Natural Flavors, Caffeine.",
"nf_calories": 100,
"nf_calories_from_fat": 0,
"nf_total_fat": 0,
"nf_saturated_fat": null,
"nf_cholesterol": null,
"nf_sodium": 25,
"nf_total_carbohydrate": 28,
"nf_dietary_fiber": null,
"nf_sugars": 28,
"nf_protein": 0,
"nf_vitamin_a_dv": 0,
"nf_vitamin_c_dv": 0,
"nf_calcium_dv": 0,
"nf_iron_dv": 0,
"nf_servings_per_container": 6,
"nf_serving_size_qty": 8,
"nf_serving_size_unit": "fl oz",
}
And this is the code that I'm trying to run:
var rp = require('request-promise');
module.exports = {
getIngredients: function(req, callback) {
rp({
method: 'GET',
uri: `https://api.nutritionix.com/v1_1/item?upc=${req.body.upc}&appId=${process.env.NUTRITIONIX_APP_ID}&appKey=${process.env.NUTRITIONIX_APPP_KEY}`
}).then((data) => {
console.log(`Talked to NutritionixAPI, result was: ${data}`);
var ingredients = data.nf_ingredient_statement.split(',');
console.log(`Ingredients split from the data are: ${ingredients}`);
return callback(ingredients);
}).catch((err) => {
console.log(`Error occured in NutritionixAPI, ${err}`)
return callback(Object.assign({}, err, { error: true }));
});
}
}
What I'm trying to figure out is why data gets printed to the console properly, but as soon as I try to access any value inside, I get the error of it being undefined. I've tried other values in the JSON as well, so I would very much appreciate the help!
EDIT: I want to clarify what the question is about, it's not about the callback and async calls because those work perfectly. My issue is specifically with var ingredients = data.nf_ingredient_statement.split(','); where nf_ingredient_statement is undefined even though obviously it isn't.
Apparently what I was getting back was a JSON string. So I just needed to do data = JSON.parse(data) to parse it into actual JSON.
The problem is that data is a JSON string so you can't access it before parsing it, that's why data.nf_ingredient_statement is undefined.
You need to parse data first, your code should be like this:
var json = JSON.parse(data);
var ingredients = json.nf_ingredient_statement.split(',');

Ionic- Angular Js - Store array locally

Hello I am developing an Ionic app and I have an array that I want to push items on to it, but not lose the data when I change screens. Also, I do not want to use a database. Is there any other way? to add to an existing array and store that array locally?
$scope.tasksCollection = [
{ info: 'Go studying', measured: 'no', total: 1, done: 1, id: 1 },
{ info: 'Go to the beach', measured: 'no', total: 1, done: 1, id: 2},
{ info: 'Run', measured: 'yes', total: 30, done: 15, id: 3}
];
$scope.tasksCollection.push({
info: $scope.taskInfo,
measured: $scope.result,
total: total,
done: 0,
id: $scope.tasksCollection.length
})
The add function is working perfectly I just loose the data when changing states.
If you want to keep data between controllers either use a service or local storage if you want to keep the data even when you quit the app.
Service example
Further angular documentation regarding services: https://docs.angularjs.org/guide/services
service.js:
angular.module('yourmodule.services')
.service('Tasks', [function () {
var collection = {
tasks: []
};
return {
getTasks : function(){ return collection.tasks; }
}
}]
);
controller.js
angular.module('yourmodule.controllers')
.controller('TaskCtrl', ['$scope', 'Tasks',
function($scope, Tasks){
$scope.Tasks = Tasks //Expose service to template
$scope.addTask = function(){
Tasks.getTasks().push({name : 'a new task'});
}
}]);
Local storage example
This is an excellent library which provides easy localstorage access for angularjs: https://github.com/grevory/angular-local-storage
angular.module('yourmodule.controllers')
.controller('TaskCtrl', ['$scope', 'localStorageService',
function($scope, localStorageService){
$scope.collection = {
tasks : localStorageService.get('tasks') || [];
}
$scope.addTask = function(){
$scope.collection.tasks.push({name : 'a new task'});
localStorageService.set('tasks', $scope.collection.tasks);
}
}]);
How about HTML5's locaStorage?
See Ionic formulas on Using Local Storage.

AngularJS $http.get php file - $injector:modulerr

I have this file api.php
require_once 'db.php';
$con = mysql_connect($host,$user,$pass);
$dbs = mysql_select_db($databaseName, $con);
$query=mysql_query("SELECT * FROM $tableName") or die(mysql_error());
$arr[];
while($obj = mysql_fetch_object($query)) {
array_push($arr, $obj);
}
echo $json_response = json_encode($arr);
It is grabbing all the data that i need.
Then i am trying to put that data into my $scope here...
// The controller
function InstantSearchController($scope, $http){
$http.get('api.php').success(function(data) {
$scope.items = data;
$scope.items = [
image : data['icon'],
english : data['english'],
british : data['british']
];
});
}
But this does work if I hard code the data like this.
function InstantSearchController($scope){
$scope.items = [
{
english: 'English A',
british: 'British A',
image: 'images/advil.jpg'
},
{
english: 'English B',
british: 'British B',
image: 'images/advil.jpg'
}
]
}
This is the error that i am seeing in the console
Uncaught SyntaxError: Unexpected token : js/angular.js:44
Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.2.15/$injector/modulerr?p0=instantSearch&p1=E…larjs.org%2F1.2.15%2F%24injector%2Fnomod%3Fp0%3DinstantSearch%0A%20%20%20%......1)
This is the fiddle trying response #1
http://jsfiddle.net/XgsWU/
And this one is for response #2
http://jsfiddle.net/JGjyS/
To anyone that might be reading this later I figured out my issues was in my controller call and i have changed/updated to this and it is working great!
app.controller('InstantSearchController', ['$scope', '$http', function($scope, $http) {
$http.get('inc/api.php').success(function(itemData) {
$scope.items = itemData;
});
}]);
Unexpected token :. This is from:
$scope.items = [
image : data['icon'],
You should use $scope.items = {...} since you want a JavaScript object with key-value pairs, not an array.
It seems like you also want to loop over data and push items onto the array:
$scope.items = [];
data.forEach(function (datum) {
$scope.items.push({
image: datum.icon,
english: datum.english,
british: datbum.british,
});
});
You have a syntax error here:
$scope.items = [
image : data['icon'],
english : data['english'],
british : data['british']
];
It should be:
$scope.items = [
{image : data['icon'],
english : data['english'],
british : data['british']}
];

AngularJS / Restangular routing "Cannot set property 'route' of undefined"

I have a AngularJS-based frontend using restangular to fetch records from a Django backend I've built.
I'm making a call for a client list with the following:
var app;
app = angular.module("myApp", ["restangular"]).config(function(RestangularProvider) {
RestangularProvider.setBaseUrl("http://172.16.91.149:8000/client/v1");
RestangularProvider.setResponseExtractor(function(response, operation) {
return response.objects;
});
return RestangularProvider.setRequestSuffix("/?callback=abc123");
});
angular.module("myApp").controller("MainCtrl", function($scope, Restangular) {
return $scope.client = Restangular.all("client").getList();
});
Chrome is showing the backend returning data with an HTTP 200:
abc123({
"meta": {
"limit": 20,
"next": "/client/v1/client/?callback=abc123&limit=20&offset=20",
"offset": 0,
"previous": null,
"total_count": 2
},
"objects": [{
"id": 1,
"name": "Test",
"resource_uri": "/client/v1/client/1/"
}, {
"id": 2,
"name": "Test 2",
"resource_uri": "/client/v1/client/2/"
}]
})
But once that happens I'm seeing the following stack trace appear in Chrome's console:
TypeError: Cannot set property 'route' of undefined
at restangularizeBase (http://172.16.91.149:9000/components/restangular/src/restangular.js:395:56)
at restangularizeCollection (http://172.16.91.149:9000/components/restangular/src/restangular.js:499:35)
at http://172.16.91.149:9000/components/restangular/src/restangular.js:556:44
at wrappedCallback (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:6846:59)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:6883:26
at Object.Scope.$eval (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:8057:28)
at Object.Scope.$digest (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:7922:25)
at Object.Scope.$apply (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:8143:24)
at done (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:9170:20)
at completeRequest (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:9333:7) angular.js:5754
I did a breakpoint on line 395 in in restangular.js:
L394 function restangularizeBase(parent, elem, route) {
L395 elem[config.restangularFields.route] = route;
The first time it hits the breakpoint elem is just an object and route has the value of client.
The second time the breakpoint is hit elem is undefined and route has the value of client.
Any ideas why elem would be undefined the second time around?
When requesting lists, Restangular expects the data from the server to be a simple array. However, if the resulting data is wrapped with result metadata, such as pagination info, it falls apart.
If you are using Django REST Framework, it will return results wrapped like this:
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"name": "Foo"
},
{
"id": 2,
"name": "Bar"
}
]
}
To translate this, you need to create a response extractor function. It's easiest to specify in the module config:
angular.module('myApp', ['myApp.controllers', 'restangular']).
config(function(RestangularProvider) {
RestangularProvider.setBaseUrl("/api");
// This function is used to map the JSON data to something Restangular
// expects
RestangularProvider.setResponseExtractor(function(response, operation, what, url) {
if (operation === "getList") {
// Use results as the return type, and save the result metadata
// in _resultmeta
var newResponse = response.results;
newResponse._resultmeta = {
"count": response.count,
"next": response.next,
"previous": response.previous
};
return newResponse;
}
return response;
});
});
This rearranges the results to be a simple array, with an additional property of _resultmeta, containing the metadata. Restangular will do it's thing with the array, and it's objects, and you can access the _resultmeta property when handling the array as you would expect.
I'm the creator of Restangular.
The restangularizeBase function is called first for your collection and then for each of your elements.
From the StackTrace, the element is OK, but once the collection is sent to restangularizeBase, it's actually undefined. Could you please console.log response.objects? Also, please update to the latest version.
Also, for the default request parameter, you should be using defaultRequestParams instead of the requestSuffix. requestSuffix should only be used for the ending "/"
Let me know if I can help you some more!

Mustache templating - presenting JSON collection

I am attempting to present a JSON collection, which is retrieved asynchronously and using FireBug I can see this ultimately looks like:
[{"Id":"00000010"},{"Id":"00000002"},{"Id":"00000003"}]
This does not work, but if I declare a collection as:
[{ "Id": "00000004" }, { "Id": "00000005" }, { "Id": "00000006"}]
This works, and then using FireBug I can see this is slightly different:
[Object { Id="00000004"}, Object { Id="00000005"}, Object { Id="00000006"}]
Why does it make a difference when retrieving the data synchronously and declaring a collection? What are my options for getting this to work.
Thanks.
UPDATE
I am also using sammy.js, here is the JavaScript:
var app = $.sammy('div[role="main"]', function () {
this.use('Mustache', 'html');
this.get('#/', function (context) {
this.load('/data')
.then(function (response) {
context.blah = 'blah';
context.data = response;
var data2 = [{ "Id": "00000004" }, { "Id": "00000005" }, { "Id": "00000006"}];
context.data2 = data2;
var templateUrl = '#Url.Content("~/Templates/template.html")';
context.partial(templateUrl);
});
});
});
$(function () {
app.run('#/');
});
Here is the template:
<h1>{{blah}}</h1>
<ul>
{{#data}}
<li>{{Id}}</li>
{{/data}}
</ul>
<ul>
{{#data2}}
<li>{{Id}}</li>
{{/data2}}
</ul>
Okay, I figured this one out!
context.data = response;
becomes
context.data = JSON.parse(response);

Categories

Resources