Access object values in array nested in JSON object - arrays

I have a GET request that sends back a JSON object structured like this:
{"ID":5176,
"DateFrom":"8/29/2018",
"DateTo":"8/29/2018",
"Units":[{"Key":"Value","Key2": "Value2"}]
}
I cannot access Units[0] value. I have tried the following:
testFunction(){
this.service.getJSON(params)
.subscribe((data) => {
this.model = data;
this.dateFrom = this.model.DateFrom;
this.dateTo = this.model.DateTo;
this.unit = this.model.Units.Key;
console.log(this.unit); //undefined
});
}
}
ngOnInit() {
this.testFunction();
}
What am I missing?

You should use
this.unit = this.model.Units[0].Key;
instead of
this.unit = this.model.Units.Key;
since Units.Key is undefined

Since Units is an array of JSONs and the array contains only one element.
It should be accessed by Units[0].
Units[0] is now a JSON, Key property is needed now.
There are 2 ways to access it
Units[0].Key
Units[0]['Key']
The final code should look like
testFunction(){
this.service.getJSON(params)
.subscribe((data) => {
this.model = data;
this.dateFrom = this.model.DateFrom;
this.dateTo = this.model.DateTo;
//first method
//this.unit = this.model.Units[0].Key;
// second method
// this.unit = this.model.Units[0]['Key'];
console.log(this.unit); //undefined
});
}
}
ngOnInit() {
this.testFunction();
}

Related

Ionic 4: 'Typescript error' in helperService Cannot read property 'length' of undefined at HelperService

Getting error 'Cannot read property 'length' of undefined at HelperService.addCommasToArray' when trying to loop through an array that has been passed as a paramter in a helperService class [Typescript]
I'm really not sure why this is not working - I believe it should be straightforward - all I'm trying to do is pass in an array as a parameter and add a ',' to every value in the array (except the last value)
Here is my HelperService Class method:
export class HelperService {
constructor() { }
/*
* Add commas to every value in the array except for the last value
*/
addCommasToArray(array: Array<any>) : Array<any> {
for (let i = 0; array.length; i++){
array[i] += ", ";
}
return array;
}
}
I then call this method within the ngInit of another ts class
this.helperService.addCommasToArray(this.previousClubs);
Here is the ngInit method
public previousClubs: Array<any>;
constructor(private playersService: PlayersService,private
helperService: HelperService, private route: ActivatedRoute) { }
ngOnInit() {
const playerId: string = this.route.snapshot.paramMap.get('id');
this.playersService.getPlayerDetails(playerId).get()
.then(playerDetailsSnapshot=> {
this.currentPlayerDetails = playerDetailsSnapshot.data();
this.currentPlayerDetails.id = playerDetailsSnapshot.id;
});
/*
* Return Previous Clubs
*/
this.playersService.getPreviousClubs(playerId).get().then(
previousClubsSnapshot =>{
this.previousClubs = [];
previousClubsSnapshot.forEach(snap => {
this.previousClubs.push({
id: snap.id,
name: snap.data().name,
});
return false;
});
});
this.helperService.addCommasToArray(this.previousClubs);
}
so here:
this.playersService.getPreviousClubs(playerId).get().then(
previousClubsSnapshot =>{
this.previousClubs = [];
previousClubsSnapshot.forEach(snap => {
this.previousClubs.push({
id: snap.id,
name: snap.data().name,
});
return false;
});
});
// this line executes without awaiting for .then enclosed scope
this.helperService.addCommasToArray(this.previousClubs);
Basically you call addCommasToArray even before your previousClubs var gets array assigned to it and then gets all its items pushed in. To fix since your method is (.then) async you need to call for this method inside the .then execution scope:
ngOnInit() {
const playerId: string = this.route.snapshot.paramMap.get('id');
this.playersService.getPlayerDetails(playerId).get()
.then(playerDetailsSnapshot=> {
this.currentPlayerDetails = playerDetailsSnapshot.data();
this.currentPlayerDetails.id = playerDetailsSnapshot.id;
});
/*
* Return Previous Clubs
*/
this.playersService.getPreviousClubs(playerId).get().then(
previousClubsSnapshot =>{
this.previousClubs = [];
previousClubsSnapshot.forEach(snap => {
this.previousClubs.push({
id: snap.id,
name: snap.data().name,
});
return false;
});
});
this.helperService.addCommasToArray(this.previousClubs);
}

Why Can't Iterate over an array in my model using the map() function

i have angular 7 component which is tied to a model and there is an array inside that model, the array was populated from a service. and it's populated.
the problem is i can't map over the array although it has elements there.
when i console it it shows the array has element. then i tried to console typeOf(array) it always gives object although it is an array !!.
i tried using this soluation but it didn't help either.
any help please?
export class FooModel {
foo : Foo
bars: Bar[];
}
export class SomeComponent implements OnInit {
model: FooModel;
constructor(private service: ProjectService) {
this.model = new FooModel();
this.model.bars = [];
}
ngOnInit() {
this.service.getFoos().subscribe((result: any) => {
// data is populated fine
this.model= <FooModel>result.data;
});
Console.log(this.model); // the model has data at this point
const arr = this.model.bars.map(a=> {
// never comes here
return a;
});
console.log(arr); // nothing is displayed here
// this works why ??
const arr2 = [1,2,3].map(s=> {
return s;
}
console.log(arr2); // it displays [1,2,3]
}
}
As the request is asynchronous, you might need to place the logic within the subscribe,
this.service.getFoos().subscribe((result: any) => {
// data is populated fine
this.model= <FooModel>result.data;
const arr = this.model.bars.map(a=> {
// never comes here
return a;
});
console.log(arr);
});
subscription is asynchronous so while it is still working the next line operation in the execution stack will be performed in this case the map you have after the subscription meanwhile it is still being populated in the background. You can try mapping in another life cycle hook say viewChecked hopefully it works. #cheers
Please look at the comments
export class FooModel {
foo : Foo
bars: Bar[];
}
export class SomeComponent implements OnInit {
model: FooModel;
constructor(private service: ProjectService) {
this.model = new FooModel();
this.model.bars = [];
}
ngOnInit() {
this.service.getFoos().subscribe((result: any) => {
// data is populated fine
this.model= <FooModel>result.data;
});
// the following starts to execute even before the model is populated above.
const arr = this.model.bars.map(a=> {
// never comes here because this.model.bars is empty at here and the length is 0 and nothing inside map executes
return a;
});
console.log(arr); // nothing is displayed here because it has nothing inside
// this works why ?? because you are using on an array which has some items.
const arr2 = [1,2,3].map(s=> {
return s;
}
console.log(arr2); // it displays [1,2,3]
}
}
So as Sajeetharan suggested, you have keep it inside subscribe()

How to return response to calling function in AngularJS?

I am calling this method testDataService, which is defined in the same JS file. This method returns a list which it gets from an API call. I want to set that value to model and return model object. but my return function is getting called before my API returns the response. How can i make sure return function will get called only after the above if block get the data from API.
getTestData(model) {
model.name = "practice";
model.value = 2;
// this if loop is calling an API and setting up data into model.
if(this.model.form.length>0 && this.model.form[0].entityName === 'test'){
let responseList;
this.testDataService(this.model).then(response => {
responseList = response;
model.class = responseList;
});
}
return this.model;
// this return function is getting called before the api returns its data. How can i make sure this return will get called only after the above if block get the data from API.
}
This is method definition
testDataService(model) {
let profileType = "test";
let profileId = "test_profile";
let configCategory = "test";
return this.referenceDataService.getTestData(profileType, profileId, configCategory);
}
You need to pass return statement from the callback, instead of placing it outside.
getTestData(model) {
model.name = "practice";
model.value = 2;
// this if loop is calling an API and setting up data into model.
if (this.model.form.length > 0 && this.model.form[0].entityName === 'test') {
this.testDataService(this.model).then(response => {
let responseList = response;
model.class = responseList;
return this.model;
}).then(response => {
return null;
});
}
}
testDataService(model) {
let profileType = "test";
let profileId = "test_profile";
let configCategory = "test";
return this.referenceDataService.getTestData(profileType, profileId, configCategory);
}

Angular service not assigning value to empty object

I have a service:
storeApp.service('currentCustomer',function($http) {
this.customerID = 0;
this.customerInfo = {}
this.customerAttributes = {}
this.getCustomerInfo = function () {
if (this.customerID != 0) {
$http.get('/customers/' + this.customerID).
then(function (result) {
this.customerInfo = result.data[0]
})
}
}
and a controller:
storeApp.controller('storeList',function($scope,$http,currentCustomer) {
$scope.changeCust = function changeCust(id) {
currentCustomer.customerID = id;
currentCustomer.getCustomerInfo()
console.log("After Change customer:")
console.log(currentCustomer)
}
$scope.selectedStore = currentCustomer
});
If I try to access selectedStore.customerID, I get values.
If I try to access selectedStore.customerInfo, I get an empty array, even though when i put console logging in to check the values, it says they are assigned.
Any ideas what I'm doing wrong? Thanks everyone.
You are manually assigning a value to CustomerId, and your service method is assigning a value to customerInfo. Except this in the service method, is not the same as this in the service. You should instantiate a var self = this; reference inside the service and use this value in all your object manipulation. eg: self.customerInfo = ....
Your reference for this has been changed inside function. first store this reference in some variable and then assign properties, some prefer to use the word self but I prefer service
storeApp.service('currentCustomer',function($http) {
var service = this;
service.customerID = 0;
service.customerInfo = {}
service.customerAttributes = {}
service.getCustomerInfo = function () {
if (service.customerID != 0) {
$http.get('/customers/' + this.customerID).
then(function (result) {
service.customerInfo = result.data[0]
});
}
}

Add variable to an existing json object

request = myService.getCases();
request.then(
function(payload) {
$scope.cases = payload.data;
var time = Math.floor((Date.now() - Date.parse($scope.cases[i].date_case_modified))/(60000*60*24));
$scope.cases.duration.push(time);
}
});
Inside the controller I am trying to tack on the cases.duration onto the cases object but it wont add it onto the object that is returned. Any ideas?
I think you just need to introduce a forEach as shown here:
request = myService.getCases();
request.then(
function(payload) {
$scope.cases = payload.data;
angular.forEach($scope.cases, function (el) {
var time = Math.floor((Date.now() - Date.parse(el.date_case_modified))/(60000*60*24));
el.duration = time;
});
}
});
Hope this helps

Resources