2

What is the best way to pass data from an http request to another component. I have programmed a user service here, which receives information about a user. Now I want to retrieve this in my login component. When I output the User Object to the console, console.log(this.user) returns undefined. Why is this and how can I solve the problem?

user.service.ts

@Injectable({ providedIn: 'root' })
export class UserService {
    user: User;

    constructor(private http: HttpClient) {}

    fetchUserByUsername(username: string){
        this.http
        .get<User>('http://localhost:8080/user/getByUsername?username=' + username)
        .subscribe(data => {
            this.user = data;
        });
        return this.user;
    }
}

login.component.ts

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css'],
  providers:[UserService]
})
export class LoginComponent {
  hide = true;
  user: User;

  constructor(private userService: UserService) { }

  validate() {
    this.user = this.userService.fetchUserByUsername('bonguen');
    console.log(this.user)
  }
}
Florian Gössele
  • 4,376
  • 7
  • 25
  • 49
Klaus M.
  • 170
  • 11
  • Javascript moves over `this.http.get` rightaway, does not block on this call. By the time you're exiting the method, the `UserService.user` is still `undefined` – Pieterjan Feb 20 '22 at 11:53
  • Does this answer your question? [How do I return the response from an Observable/http/async call in angular?](https://stackoverflow.com/questions/43055706/how-do-i-return-the-response-from-an-observable-http-async-call-in-angular) – R. Richards Feb 20 '22 at 11:58

3 Answers3

2

It's undefined is that you are making an asynchronous operation, To resolve you can do this in your component,

Change your service method as,

fetchUserByUsername(username:string){
    return this.http.get<User>(`http://localhost:8080/user/getByUsername?username='+username`)
}

and in component,

 validate() {
     this.http.fetchUserByUsername('bonguen')
    .subscribe(data => {
        this.user = data;
    });
  }
Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
  • Thanks for your answer! Is this the best way to solve this issue ? I always thought it would be better to call the subscription in the service – Klaus M. Feb 20 '22 at 12:14
  • You might use this method across different components, so its better to call within the components than in the service. Still you can do within the service but make sure you use async method and return the user – Sajeetharan Feb 20 '22 at 12:15
  • Right way to go, since this is how you should work with rxjs. This could lead to an excessive number of requests to the user api though, so you should also look into `ReplaySubject` (or `shareReplay`) – efkah Feb 20 '22 at 12:32
  • I did the same, but still is undefined, this a copy paste of the same 'solutions' – fsalazar_sch Oct 02 '22 at 09:07
2

You should always return the Observable or Promise from your service. You should not persist the data in the service

@Injectable({ providedIn: 'root' })
export class UserService {
    
    constructor(private http:HttpClient) {}

    fetchUserByUsername(username:string) {
      return this.http.get<User>('http://localhost:8080/user/getByUsername', { queryParams: { username } });
    }
}

In the component

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent {
  hide = true;
  user:User;

  constructor(private userService: UserService) { }

  validate() {
    this.userService.fetchUserByUsername('bonguen').subscribe(user => {
      this.user = user;
      console.log(this.user);
    }
  }
}
Florian Gössele
  • 4,376
  • 7
  • 25
  • 49
Pieterjan
  • 2,738
  • 4
  • 28
  • 55
0

the api call is async so return this.user; gets called before the API gets finished loading, that's why you're getting undefined value . to solve this issues , so the subscription from the login component like

  validate() {
this.userService.fetchUserByUsername('bonguen').subscribe((res)=>{
  console.log(res , 'user')
})

here is a working example https://stackblitz.com/edit/angular-service-h6x2bp?file=app%2Flogin%2Flogin.component.ts

Faizal Hussain
  • 1,551
  • 2
  • 10
  • 18