Angular 4 load data before initialize the application

11,662

Solution 1

I've found a workaround on this question.

I found a way to use canActivate. I had already tried to use .map() to return an Observable, but the key point is the .first() at the end, this is waht solved the issue.

I'll keep it open tho, because if there is a way to achieve the same result using Resolve, maybe it is better.

Solution 2

A few things ...

Pre-fetching data before a page loads is a great use of a resolver.

Preventing access to a route is a great use of CanActivate.

Note however that the resolver only works AFTER all guards are checked. So your code will attempt to run the CanActivate before running the resolver.

enter image description here

Solution 3

I think you can use APP_INITIALIZER to load data before application starts.

Check this article:

https://devblog.dymel.pl/2017/10/17/angular-preload/

Share:
11,662

Related videos on Youtube

celsomtrindade
Author by

celsomtrindade

Amante dos códigos. Fascinado pela mágica digital. "Nunca subestime a capacidade de um usuário. Ele irá quebrar o mais simples dos códigos, com o mais simples uso de interface."

Updated on June 04, 2022

Comments

  • celsomtrindade
    celsomtrindade almost 2 years

    I'm trying to load some data before my application starts. The reason why I need to do it, is because some of the menu has restricted access based on some user condition, for example, based on the user location.

    So if the user doesn't have a location yet or it's location isn't enabled to access certain view, I need to block it.


    I tried to use Angular Resolve method, without success, this is what I did:

    Resolve guard

    // The apiService is my own service to make http calls to the server.
    @Injectable()
    export class AppResolveGuard implements Resolve<any> {
        constructor(
            private _api: ApiService,
            private _store: Store<IStoreInterface>,
        ) { }
    
        resolve(): any {
            return this._api.apiGet('loadData').subscribe(response => {
                this._store.dispatch({
                    type: USER_FETCH_DATA,
                    payload: response.usuario
                });
    
                return response;
            });
        }
    }
    

    Routing

    export const routing = [
        {
            path: '', component: AppComponent, canActivateChild: [AuthGuard], resolve: {app: AppResolveGuard},
            children: [
                { path: 'home', component: HomeComponent },
                { path: 'company', canActivate: [LocationGuard], component: CompanyComponent },
            ]
        }
    ];
    

    The AuthGuard is just going to check for a valid cookie session.

    As you can see, the routing I'm trying to block access is the company routing. I'm able to prevent access when I first load another page, for example, if the first access is to the page home and then I navigate to the page company the validation works fine, because the user data and location is already avaliable.

    However, if the first access is to the page company, it will block all users to navigate there, because at the time the LocationGuard try to validate the user location, the data isn't avaliable yet.

    I also tried to replace Resolve with CanActivate, but it never enables the view after the data is avaliable, it stays on a blank page.

    • angularrocks.com
      angularrocks.com over 6 years
      try to look in to this one stackoverflow.com/a/45204693/415078 basically you can call you api before you bootstrap AppModule and then you can pass/access that data up in your guards
    • celsomtrindade
      celsomtrindade over 6 years
      @Kuncevic cant it be solved using the angular router? Because it's all linked with the store, etc..
    • angularrocks.com
      angularrocks.com over 6 years
      Then sounds like you cant do that before app initialize as you rely on store, etc
  • celsomtrindade
    celsomtrindade over 6 years
    Hum.. So going with canActivate (like I'm commenting on my own answer here) is the way to go?
  • DeborahK
    DeborahK over 6 years
    I don't understand your requirements well enough. But one option is to add the resolve to the parent route and the canActivate onto the child routes. That way the resolve should execute before the child's canActivate's run.
  • Hadrien TOMA
    Hadrien TOMA over 3 years
    @DeborahK can you help me to locate where this schema is in the official documentation of Angular? I easily find the schema for component lifecycles but I don't reach to find the one you provided regarding guards and resolvers 😢.
  • DeborahK
    DeborahK over 3 years
    It is somewhat discussed here: angular.io/guide/router-tutorial-toh#milestone-5-route-guard‌​s Is that what you are looking for?