ADEXITUM
ADEXITUM

Reputation: 11

Local storage is not defined when try to fire any http request in AppComponent in Angular 17

In Angular 17 running in Docker I've got standalone AppComponent that contains <router-outlet></router-outlet>.

When I try to subscribe to any http request in app.component.ts, app doesn't rebuild and throws an error:

_Observable {
   source: _Observable {
     source: _Observable {
       source: [_Observable],
       operator: [Function (anonymous)]
     },
     operator: [Function (anonymous)]
   },
  operator: [Function (anonymous)]
}

ERROR ReferenceError: localStorage is not defined

how I try to subscribe to http request: this._authService.isAdmin().subscribe() isAdmin() method in my service:

  isAdmin(): Observable<any> {
    return this._http.get(LARAVEL_URL + '/api/auth/isAdmin')
  }

Anyway the same problem with any request. While this error persists localStorage in DevTools becomes empty.

I also have interceptor and AuthGuard that guards component at the route '/'.

Interceptor:

export const authInterceptor: HttpInterceptorFn = (
  req: HttpRequest<any>,
  next: HttpHandlerFn
): Observable<HttpEvent<any> | any> => {
  const token = localStorage.getItem('auth_token');

  if(token) {
    const cloned = req.clone({
      setHeaders: {
        Authorization: `Bearer ${token}`,
      },
    });
    return next(cloned);
  } else {
    return next(req);
  }
};

AuthGuard:

export class AuthGuard implements CanActivate {
  constructor(
    private authService: AuthService, 
    private router: Router
  ) {}

  canActivate(): boolean {
    if (this.authService.isAuthenticated()) {
      return true;
    } else {
      this.router.navigate(['/auth']);
      return false;
    }
  }
}

How my routes are guarded:

  { path: '', component: MainComponent, canActivate: [AuthGuard]},

How I provide my authInterceptor:

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(withInterceptors([authInterceptor]), withFetch()),
  ],
};

I tried to perform http request in another component and import it to AppComponent but it still got the same error.

It's important to make request at app component becuase eventually I want to wrap routerOutlet with MatSideNav from material UI and make my whole app contain sideNavigation. In order to switch content of matSideNav I need http request.

Upvotes: 1

Views: 409

Answers (1)

Naren Murali
Naren Murali

Reputation: 58199

On the server localStorage is non existant, so we should check ifs the server and set a default value and avoid accessing the localStorage! We can perform this check by using the below function and token! You could store the token in a service and access that directly instead of localstorage when on the server, so that the API calls do not fail!

isPlatformBrowser

PLATFORM_ID

export const authInterceptor: HttpInterceptorFn = (
  req: HttpRequest<any>,
  next: HttpHandlerFn
): Observable<HttpEvent<any> | any> => {
  const platformId = inject(PLATFORM_ID);
  const token =  isPlatformBrowser(platformId) ? localStorage.getItem('auth_token') : 'some default auth token';

  if(token) {
    const cloned = req.clone({
      setHeaders: {
        Authorization: `Bearer ${token}`,
      },
    });
    return next(cloned);
  } else {
    return next(req);
  }
};

Upvotes: 0

Related Questions