1

In My Angular Application

I made several attempts to get the values using a BehaviorSubject to know when the value was changed or received. I can not get the values before loading the component.

Through this link you can see what you are returning:

https://dev.moip.com.br/v1.5/reference#listar-planos

data.service.ts:

dataOnChanged: BehaviorSubject<any> = new BehaviorSubject({});

getData() {
    return new Promise((resolve, reject) => {
        this.http.get(this.api_URL + 'plans/, this.httpOptions).subscribe((data: any) => {

            // the result is
            // data = {plans: Array(5)}

            this.dataOnChanged.next(data);
            resolve(data);
        },
            (response: any) => {
                reject(response.error);
            });
    });
}

resolve.service.ts:

constructor(
    private dataService: DataService, {
}

* Resolve
 * @param {ActivatedRouteSnapshot} route
 * @param {RouterStateSnapshot} state
 * @returns {Observable<any> | Promise<any> | any}
 */
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {
    return new Promise((resolve, reject) => {
        Promise.all([
            this.dataService.getData()
        ]).then(
            () => {
                resolve();
            },
            reject
        );
    });
}

routes.module.ts:

        {
            path: 'home',
            component: HomeComponent,
            resolve: {
                data: ResolveService,
            },
        },

home.component.ts:

constructor(
    public data: DataService,
) {

    this.dataService.dataOnChanged.subscribe((result: any) => {
        // no result
        debugger;
    });

The problem is that I can not load the data returned by HTTP GET before loading the component. I need to load the data before and show the screen.

Luiz Ricardo Cardoso
  • 1,554
  • 4
  • 16
  • 37
  • So you're saying that `home.component` should not be visible until the GET has returned, is that right? – user184994 May 26 '18 at 17:33
  • That's right, I need to load the data before ... To later display in HTML using angularinterpolation. – Luiz Ricardo Cardoso May 26 '18 at 17:35
  • Have a look at `RouteResolvers`, sounds like what you're wanting https://alligator.io/angular/route-resolvers/ – user184994 May 26 '18 at 17:36
  • Actually the component is being loaded only after receiving the data, but I can not get the data in the component using subscribe. – Luiz Ricardo Cardoso May 26 '18 at 17:38
  • Sorry, I think I understand the problem now. Which `providers` array have you added the `DataService` to? Is it provided at the correct level to ensure the component and resolve service are using the same instance? – user184994 May 26 '18 at 17:41
  • I wear @Injectable({ providedIn: 'root' }) in all services. – Luiz Ricardo Cardoso May 26 '18 at 17:44
  • Check this question out. It might help you. https://stackoverflow.com/questions/50459815/how-to-organize-angular-data-service/50460681#50460681 – Bunyamin Coskuner May 26 '18 at 17:50
  • I don't understand why you want to get the data before you load the component ? The service instance will be created when the component initializes. – Florian May 26 '18 at 17:51
  • I do not want to load before receiving the data because if I display the component before getting the data, will not appear the values on the screen ... just want to load the component when I get the values to be displayed on the screen. – Luiz Ricardo Cardoso May 26 '18 at 18:07
  • Your value will be display on the screen with observable pattern, I'm writing an answer and I maybe have a training project on my github I can show you (I'm still a beginner) – Florian May 26 '18 at 18:12
  • The moment I open the screen, it appears blank ... after a few seconds after running HTTP GET the value is returned and there it is displayed. But I want it when you open the screen, the data is already loaded and ready to be displayed. So the use of resolves. – Luiz Ricardo Cardoso May 26 '18 at 18:16

2 Answers2

0

Usage of BehaviorSubject is redundant over here instead you can access the resolved data using the data property of ActivatedRoute’s snapshot object or subscribe to ActivatedRoute data Property which holds the static and resolved data of the current route
it's recommended to use Observables over promises. By converting to a promise you will lose the ability to cancel a request and the ability to chain RxJS operators.

From Docs

  1. Rely on the router to call the resolver. Don't worry about all the ways that the user could navigate away. That's the router's job. Write this class and let the router take it from there.

  2. The observable provided to the Router must complete. If the observable does not complete, the navigation will not continue.

data.service.ts:

 getData():Observable<any> {
        return this.http.get(this.api_URL + 'plans/, this.httpOptions);
            }

resolve.service.ts:

import { Injectable } from '@angular/core';
    import { Resolve } from '@angular/router';
   import {Observable} from 'rxjs';

    @Injectable()
    export class resolver implements Resolve<Observable<any>> {
      constructor(private service:Service) {}

      resolve() {
        return this.dataService.getdata();
      }
    }

routes.module.ts:

 {
            path: 'home',
            component: HomeComponent,
            resolve: {
                data: resolver,
            },
        },

home.component.ts:,

  constructor( private route:ActivatedRoute) {
                 this.route.data.subscribe(value=>{
                       console.log(value);
                       });}

or

 constructor( private route:ActivatedRoute) {
                 this.item=this.route.snapshot.data;
                    console.log(this.route.snapshot.data);
                     }

STACKBLITZ DEMO

Vikas
  • 11,859
  • 7
  • 45
  • 69
  • Hi if this or any answer has solved your question please consider accepting it by clicking the check-mark. This indicates to the wider community that you've found a solution and gives some reputation to both the answerer and yourself. There is no obligation to do this. – Vikas Jun 24 '18 at 18:29
0

I think the best way to get the value will be to get it from the ActivatedRoute

In your component, if you inject the ActivatedRoute:

constructor(ars: ActivatedRoute) {
  console.log(ars.snapshot.data.data) // This will log your value here
}

That way, you don't need the BehaviourSubject.

Here is an example on StackBlitz.

When you visit the /about route, it will get a value on a 2second delay to demonstrate

user184994
  • 17,791
  • 1
  • 46
  • 52