0

I want to save and access to the Angular2 object but I am getting undefined as value. I am getting a object but this not accessible such as array. How can I do it as array?

Node.js api.js

api.get('/getData', function(req, res){
  res.send({name:'test'})
});

Dataservice PassProfileDataService.ts

import {Component, Injectable} from '@angular/core'
import { Http} from "@angular/http";


@Injectable()
export class PassProfileDataService {

constructor(private http: Http) {}

getItems(){
    return this.http.get('/api/getData').map((res:any) => res);
}
}

Component which consumes the service

import {Component, Input, OnInit} from '@angular/core';
import {PassProfileDataService} from '../common/PassProfileDataService';


@Component({
styleUrls:['/assets/css/bootstrap.css', '/assets/css/profile.css'],
    selector: "profile",
    templateUrl: `client/components/profile/profile.component.html`

})

export class ProfileComponent implements OnInit {

items:any;

constructor(private _sharedService: PassProfileDataService){}

ngOnInit(){
    this.items = this._sharedService.getItems();
    console.log(this.items + ' test');
}

}

The view component profile.component.html

<div *ngFor="let i of items">
{{i.name}} 
</div>

I am getting following Exception:

core.umd.js:3462 EXCEPTION: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

3 Answers 3

2

this.items.subscribe(...) is asynchronous meaning that it won't run that code right now. this.items is an Observable which in short means that when something happens eventually, you can be notified and "Observe" the event or series of events when they happen. In this case it looks like it works a lot like a promise for the response to getUserWishList(). I've written a lot of code that looks just like this.

If all goes according to plan, eventually the subscription to the observable will fire and this.data will equal value but I can guarantee that it won't happen by the next line when you try and print it out.

this.items.subscribe(value => console.log(value)); works because when the event eventually does fire you have value and can print it.

this.items.subscribe(value => this.data = value); also works. Eventually. It just won't be done as fast as you're expecting.

You could modify your code a little to be both:

this.items.subscribe(value => {
  this.data = value;
  console.log(this.data);
});

You'll see the value in the console and if anything is bound to this.data it should also reflect the data in the view. This can be a little tricky though, you'll get an error if you try to bind data.name in the view if this.data doesn't hold anything before the Observable comes back.

Sign up to request clarification or add additional context in comments.

5 Comments

I am getting following error client/components/profile/profile.component.ts(27,6): error TS2322: Type 'any[]' is not assignable to type 'Observable<any[]>'. [1] client/components/profile/profile.component.ts(27,6): error TS2322: Type 'any[]' is not assignable to type 'Observable<any[]>'. [1] Property '_isScalar' is missing in type 'any[]'. Also how can I access then the name property?
@Tony that is a more complicated typing problem probably worthy of a new question. You'd have to show quite a bit more of your code for us to see what getUserWishList actually returns (an Observable, but what's the generic type? i.e. Observable<?>) and what value really is.
@Tony, from your console.log image you have in your question it looks like value is just an object and not an array. From that I'd assume value is an any and this.data should not be an Observable of any kind, this.data should just be an any. Or better yet, a properly defined interface.
Hi Corey, please see the code above. I add a full example of my code what I am trying to do. I am getting a object [object Object] but I can not traverse these.
1) In your service, don't just return the response object, you should use res.text() or res.json() so you actually have the response data. 2) Double check that the API is actually returning an array of objects. You're setting this.items to an object and not an array therefore ngFor can't iterate over it. 3) This one is my personal opinion that I find produces easier to maintain code: Use any as little as possible. Be as explicit as possible so that Typescript can help find problems before they're problems. Use Typescript's noImplicitAny and noImplicitReturns compiler flags.
1

This is because of async behavior of framework. Code does not wait for your service to return. It proceeds to next statement and at that point of time, "data" is undefined. Change following of your code:

this.items.subscribe(value => this.data = value);
console.log(this.data);

to:

this.items.subscribe(value => {
this.data = value;
console.log(this.data);
});

Do you see the difference? I moved console.log to success block of service call. This is one quick way of making your code run in synchronus manner. There are other ways as well to bring synchronus behavior in your code when you need i.e. Observable.forkJoin. Hope you got the idea.

Comments

0

TypeScript allows you to access the outer function scope when defining a function, using arrow notation, by wrapping the parameters in parentheses.

To save the value of data simply use:

this.items.subscribe((value) => this.data = value);

And to save the data and then output it as soon as it arrives you can use:

this.items.subscribe((value) => {
    this.data = value;
    console.log(this.data);
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.