1
votes

Is it possible to use Leaflet with angular/universal? How can I avoid to build Leaflet within server?

After npm run build:prod dist folder is generated. But when I run node server.js I get following error:

var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer; Window is not defined.

3
check platform id and if it's server don't render leaflet component using *ngIf for exampleKasabucki Alexandr

3 Answers

4
votes

I solved this by mocking window, navigator and document with Mock Browser

Just install the mock browser pacakge npm i mock-browser

And add the following code to your server.ts:

const MockBrowser = require('mock-browser').mocks.MockBrowser;
const mock = new MockBrowser();


global['window'] = mock.getWindow();
global['document'] = mock.getDocument();
global['navigator'] = mock.getNavigator();
3
votes

After hours of searching I found a solution. You need to use Leaflet with custom service.

leaflet.service.ts


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

@Injectable()
export class LeafletService {

  public L = null;

  constructor(@Inject(PLATFORM_ID) private platformId: Object) {
    if (isPlatformBrowser(platformId)) {
      this.L = require('leaflet');
    }
  }

}

map.component.ts

constructor (
    private leafletService: LeafletService
) {}

ngAfterViewInit() {
    ...
    this.leafletService.L.map('map').setView([51.505, -0.09], 13);
    ...
}

There is also an example on GitHub

0
votes

As per the error you are getting you should need to add the platform browser check if you are rendering your application from server, because keywords like window, document etc are not available on server. so add checks like this -

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

export class XYZ implements OnInit{
    constructor(@Inject(PLATFORM_ID) private platform: any) { }
    ngOnInit() {
        if (isPlatformBrowser(this.platform)) {
            // use window, document keywords here
        }
    }
}