Prabhu Arumugam Prabhu Arumugam - 3 months ago 33
TypeScript Question

Angular2 Service Subscribe not working

Hi I cannot store data into UserDetailsArr object , PFB code for your reference.

User Details Class:

export class UserDetails
{
userId:string;
userName:string;
password:string;
firstName:string;
lastName:string;
mobileNumber:string;
email:string
}


Service Class:

import {Component} from '@angular/core'
import {OnInit} from '@angular/core'
import {UserService} from './user.service'
import {User} from './user'
import {UserDetails} from './user'
import {UserDetailComponent} from './user-detail.component'
import {HTTP_PROVIDERS} from '@angular/http';

@Component(
{
selector:'user-list',
template: `
<br/><br/><br/>
<div>
<table border='1'>
<thead>
<tr>
<th>First Name </th>
<th>Last Name </th>
<th>Mobile Number </th>
<th>Email </th>
</tr>
</thead>
<tr *ngFor="let user of UserDetailsArr">
<td> <span (click)="showDetails(user)"> {{user.firstName}} </span> </td>
<td> {{user.lastName}} </td>
<td> {{user.mobileNumber }} </td>
<td> {{user.email}} </td>
</tr>
</table>
</div>
<user-detail *ngIf = "selectedUser != null" [user] = "selectedUser"></user-detail>
<br/><br/><br/>

`,
providers:[UserService , HTTP_PROVIDERS],
directives:[UserDetailComponent]
}
)
export class UserListComponent implements OnInit
{
users:User[];
UserDetailsArr: UserDetails[]= [];
errorMessage: string = '';
isLoading: boolean = true;
public selectedUser = null;
constructor(private _userService:UserService)
{

}

ngOnInit():any
{
this.getUsers();
}

getUsers()
{

this._userService.getUsers()
.subscribe(
/* happy path */ p => this.UserDetailsArr = p,
/* error path */ e => this.errorMessage = e,
/* onComplete */ () => this.isLoading = false);


console.log(this.UserDetailsArr);
}

showDetails(user)
{
this.selectedUser = user;
}



}


web Service is working perfecltly If I log like below,

this._userService.getUsers()
.subscribe(
/* happy path */ p => console.log(JSON.stringify(p),
/* error path */ e => this.errorMessage = e,
/* onComplete */ () => this.isLoading = false));


user data has logged in browser console.

[{"UserId":"bcb444aa-401b-48a7-b1bf-17b4bf78b834","UserName":"prabhu","Password":"pwd","FirstName":"PRABHU","LastName":"ARUMUGAM","MobileNumber":"1234567890","Email":"prabhu@gmail.com"},
{"UserId":"d9e5ba40-d0d7-4d90-89b0-7e26660cc84b","UserName":"senthil","Password":"pwd","FirstName":"SENTHIL","LastName":"KUMAR","MobileNumber":"1234567890","Email":"senthil@gmail.com"},
{"UserId":"a59dabad-5a8c-4ced-9006-2181bf8c10cb","UserName":"vijay","Password":"pwd","FirstName":"VIJAY","LastName":"RAJ","MobileNumber":"1234567890","Email":"vijay@gmail.com"},
{"UserId":"f3e2d351-9413-4d80-8623-36556d27f875","UserName":"thamizh","Password":"pwd","FirstName":"THAMIZH","LastName":"VANAN","MobileNumber":"1234567890","Email":"thamizh@gmail.com"}]
(e) { return _this.errorMessage = e; } () { return _this.isLoading = false; }


But if I assign the data to UserDetailsArr data is not assigned,

this._userService.getUsers()
.subscribe(
/* happy path */ p => this.UserDetailsArr = p,
/* error path */ e => this.errorMessage = e,
/* onComplete */ () => this.isLoading = false);
console.log(this.UserDetailsArr);


Next line I tried to print but its not working, result is undefined :-(

Please help me out.. :-(.. Sorry for long post...

Answer

Observables call the callbacks passed to subscribe(...) or other operators like map(...) when data arrives.

The code after subscribe(...) is called immediately afterwards and as @JbNizet mentioned this is usually long before data arrives.

You need to move code that depends on the data received from the observable into one of the callbacks like:

 this._userService.getUsers()
       .subscribe(
            /* happy path */ p => {
                this.UserDetailsArr = p;
                console.log(this.UserDetailsArr);
            }),
             /* error path */ e => this.errorMessage = e,
             /* onComplete */ () => this.isLoading = false);  
Comments