Skip to content

Solving the “navigator is not defined” Error in Angular

This error typically occurs when you’re trying to use browser-specific APIs (like navigator) during server-side rendering (SSR) or in a non-browser environment. Here’s how to fix it:

Root Cause

The error happens because:

  1. Your application is trying to access the navigator object
  2. This object only exists in browser environments
  3. During server-side rendering or build time, this object isn’t available

Solutions

1. Check for Browser Environment (Recommended)

Wrap any navigator usage in a browser check:

import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';

constructor(@Inject(PLATFORM_ID) private platformId: Object) {}

someMethod() {
  if (isPlatformBrowser(this.platformId)) {
    // Safe to use navigator here
    console.log(navigator.userAgent);
  }
}

2. Lazy Load Browser-Specific Code

Move browser-dependent code to components that only load in the browser:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-browser-component',
  template: '<div *ngIf="isBrowser">Browser content</div>'
})
export class BrowserComponent implements OnInit {
  isBrowser = false;

  ngOnInit() {
    this.isBrowser = typeof window !== 'undefined' && typeof navigator !== 'undefined';
  }
}

3. Use Angular Universal Correctly

If you’re using Angular Universal (SSR), ensure proper configuration:

  1. In your server.ts:
import { ngExpressEngine } from '@nguniversal/express-engine';

server.engine('html', ngExpressEngine({
  bootstrap: AppServerModule,
  providers: [
    provideModuleMap(LAZY_MODULE_MAP)
  ]
}));
  1. Add browser providers in app.server.module.ts:
@NgModule({
  providers: [
    { provide: 'REQUEST', useValue: req },
    { provide: 'RESPONSE', useValue: res }
  ]
})
export class AppServerModule {}

4. Common Fixes for Specific Cases

For Geolocation:

getLocation() {
  if (typeof navigator !== 'undefined' && navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(position => {
      console.log(position);
    });
  }
}

For Service Workers:

registerServiceWorker() {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js');
  }
}

5. Update Angular CLI and Dependencies

Ensure you’re using compatible versions:

ng update @angular/cli @angular/core

Additional Checks

  1. Verify you don’t have direct navigator calls in your component constructors
  2. Move all browser API calls to lifecycle hooks (ngOnInit, ngAfterViewInit)
  3. Check third-party libraries that might be using browser APIs

Example Fix for Your Case

Based on your error stack trace, you likely need to:

  1. Add platform checking to your component:
import { Component, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';

@Component({...})
export class YourComponent {
  isBrowser: boolean;

  constructor(@Inject(PLATFORM_ID) platformId: Object) {
    this.isBrowser = isPlatformBrowser(platformId);
  }

  browserMethod() {
    if (this.isBrowser) {
      // Safe to use navigator here
    }
  }
}
  1. Update your template to conditionally render browser-only content:
<div *ngIf="isBrowser">
  <!-- Browser-specific content -->
</div>

This should resolve the “navigator is not defined” error while maintaining functionality in both server and browser environments

Leave a Reply

Discover more from Sowft | Transforming Ideas into Digital Success

Subscribe now to keep reading and get access to the full archive.

Continue reading