Code Ratchet
Code Ratchet

Reputation: 6029

Can't access array values when looping, but values appear with writing to the console

I'm experiencing a very strange issue, I retrieve the users profile from Firebase inside this profile is an Photo Object basically an array of photos the user has uploaded.

My get Profile method:

getUserProfile(): Observable<User> {

    var userId = null;

    var auth = this.af.auth.subscribe(user => {
        userId = user.uid;
    });

    auth.unsubscribe();

    return this.af.database.object('/users/' + userId)
        .map(pro => new User(
            pro.$key,
            pro['email'],
            pro['gender'],
            pro['last_name'],
            pro['first_name'],
            pro['display_name'],
            pro['photos'],
            pro['hobbies']))
}

My user class is as follows:

export class User {
    public constructor(
        public userId: string,
        public email: string,
        public gender?: string,
        public last_name?: string,
        public first_name?: string,
        public display_name?: string,
        public photos: Photo[] = [],
        public hobbies: Hobbies[] = [],
    ) { }
}

Inside my component I call the getUserProfile as so:

this.userSubscription = this.profileService.getUserProfile().subscribe(profile => {
   console.log(profile.photo);
});

When I write console.log(profile.photos); I see the following:

enter image description here

Yet when I try to loop through this collection by doing the following:

for(var i = 0; i < profile.photos.length; i++){
   console.log('here');
}

Nothing is written to the console, even when I do the following:

console.log(profile.photos.length); it says undefined....

I'm not entirely sure what is going wrong, can anyone spot the reason into why I can't loop through the photo array and access the properties?

Upvotes: 0

Views: 273

Answers (3)

Diullei
Diullei

Reputation: 12434

The profile.photos is an object and not an array. Try to change the photos member on you interface to:

public photos: {[index: string]: Photo} = {}

So, to iterate this object you can do:

for(let key in profile.photos) { 
    let photo = profile.photos[key];
    //... 
}

UPDATE

If you want to see other options to get all property values from a javascript Object see this: How to get all properties values of a Javascript Object (without knowing the keys)?

Upvotes: 1

Aluan Haddad
Aluan Haddad

Reputation: 31873

All you need is something like this, give it a try

service.ts

import 'rxjs/add/operator/mergeMap';

import {User} from './user';

export default class Service {
  getUserProfile(): Observable<User> {
    return this.af.auth.flatMap(({ id }) =>
      this.af.database.object('/users/' + id)
    );
  }
}

component.ts

import Service from './service';

export class Component {
  constructor(readonly service: Service) { }

  ngOnInit() {
    this.service.getUserProfile().subscribe(({ photos = [] }) => {
      photos.forEach(console.log);
    });
  }
}

user.ts

export interface User {
  userId: string,
  email: string,
  gender?: string,
  last_name?: string,
  first_name?: string,
  display_name?: string,
  photos: Photo[],
  hobbies: Hobbies[];
}

No manual deserialization lining up keyed values by name to shove them into a meaningless User class, just use an interface. No mutable security variables. No subscriptions to worry about, for the time being. Just get the basic problem right.

Upvotes: 0

Vivek
Vivek

Reputation: 1525

for syntax is breaking your code.Try this.

this.userSubscription = this.profileService.getUserProfile().subscribe(profile => {
console.log(profile.photo);
  for (let entry of profile.photo) {
       console.log(entry); 
  }
});

Reference : https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html

Upvotes: 0

Related Questions