0

I have an angular service which is used as mid point to fetch data from database. Here is it:

export class WebService {
constructor(private http: Http, private datePipe: DatePipe) {
    this.getStatsbyDate(this.datePipe.transform(new Date(), 'dd-MM-yyyy'));
}
statsModel = {
    date: this.datePipe.transform(new Date(), 'dd-MM-yyyy'),
    answeringMachine:0,
    hangUp: 0,
    conversations: 0
};
getStatsbyDate(date) {
    this.http.get(this.BASE_URL + '/stats/' + date)
      .subscribe(
        res => {
            this.btnsOnResponse = true; 
            this.statsModel = res.json(); 
            // console.log(this.statsModel);                              
        },
        err => {
            console.log("Couldn't fetch data")
        }
    );
}

I am trying to access the fetched data in one of my angular components this way

export class FusionChartsComponent implements OnInit {
  constructor(private webService: WebService) {}
  ngOnInit() {
     console.log(this.webService.statsModel.answeringMachine);
  }
}

I am not sure at all why this is happening. Please advise!

1 Answer 1

2

As shown in the documentation here: https://angular.io/guide/http, move the subscribe to the component. Then you can add whatever code you need within the subscribe.

getStatsbyDate(date) {
    this.http.get(this.BASE_URL + '/stats/' + date)
      .pipe(
        tap(res => {
            this.btnsOnResponse = true; 
            this.statsModel = res.json(); 
            // console.log(this.statsModel);                              
        }),
        catchError(err => console.log("Couldn't fetch data"))
    );
}

export class FusionChartsComponent implements OnInit {
  constructor(private webService: WebService) {}
  ngOnInit() {
     this.webService.getStatsbyDate().subscribe(
         data => {
             console.log(data);
             console.log(this.webService.statsModel.answeringMachine);
     });
  }
}

EDIT

If you need the service to retain its data to share with other components, you can do something like this:

@Injectable()
export class MovieService {
    private moviesUrl = 'api/movies';
    private movies: IMovie[];

    constructor(private http: HttpClient) { }

    getMovies(): Observable<IMovie[]> {
        if (this.movies) {
            return of(this.movies);
        }
        return this.http.get<IMovie[]>(this.moviesUrl)
                        .pipe(
                            tap(data => console.log(JSON.stringify(data))),
                            tap(data => this.movies = data),
                            catchError(this.handleError)
                        );
    }
}

Each component can subscribe like this:

this.movieService.getMovies().subscribe(
    (movies: IMovie[]) => this.movies = movies,
    (error: any) => this.errorMessage = <any>error
);

The first component that calls the service will cause it to send the http get request which will get the data. It then stores that data in a private property. All other calls with get the already retrieved data (as shown in the if block).

Since all of the components are subscribing, you can add whatever code within the subscribe method. That code will then not execute until it has the data it needs.

Most developers consider it to be "best practice" to subscribe as close to the UI as possible. This also makes it much easier to write code that is only executed after the data is returned.

I have a complete example of this here: https://github.com/DeborahK/MovieHunter-communication/tree/master/MH-Take4

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

1 Comment

Thanks @DeborahK .But I am accessing the same service from other components as well on launch. Is there any work around for that.

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.