I'm a recent angular user. I'm trying to add a leaflet map to my project. I saw that I had to use a service to avoid errors related to window. I used the following example: https://github.com/NickToony/universal-starter-leaflet-example
I made my map.service.tst
file like this:
import { Injectable, PLATFORM_ID, Inject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
@Injectable()
export class MapService {
public L = null;
constructor(@Inject(PLATFORM_ID) private platformId: Object) {
if (isPlatformBrowser(platformId)) {
this.L = require('leaflet');
}
}
}
and my map.component.ts
file like this:
import { Component, OnInit } from '@angular/core';
import { MapService } from '../services/map.service';
import { Map } from 'leaflet';
@Component({
selector: 'app-map',
standalone: true,
imports: [],
templateUrl: './map.component.html',
styleUrl: './map.component.css',
})
export class MapComponent implements OnInit {
public message!: string;
private map!: Map;
constructor(private mapService: MapService) {}
ngOnInit() {
if (this.mapService.L) {
// Leaflet is loaded - load the map!
this.message = 'Map Loaded';
this.setupMap();
} else {
// When the server renders it, it'll show this.
this.message = 'Map not loaded';
}
}
private setupMap() {
if (!this.mapService || !this.mapService.L) {
console.error('mapService is not initialized');
return;
}
// Create the map in the #map container
this.map = this.mapService.L.map('map').setView([51.505, -0.09], 13);
// Add a tilelayer
this.mapService.L.tileLayer(
'http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png',
{
attribution:
'copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>,' +
' Tiles courtesy of <a href="http://hot.openstreetmap.org/" target="_blank">Humanitarian OpenStreetMap Team</a>'
}
).addTo(this.map);
}
}
in map.component.ts
, I have two errors:
The 'map' property doesn't exist on the 'never' type.
The 'tileLayer' property doesn't exist on the 'never' type.
I can't figure out how to get past these two errors.
Nick Felker already provided a great answer why you get these errors. You may also be able to use @types/leaflet
instead of writing your own typings.
However, you don't really need that service. Here is another example using Angular with Leaflet:
ng new leaflet-angular-example
npm install leaflet
npm install --save-dev @types/leaflet
ng g component map
app.component.html
<main>
<router-outlet></router-outlet>
</main>
app.routes.ts
import { Routes } from '@angular/router';
import { MapComponent } from './map/map.component';
export const routes: Routes = [
{ path: 'map', component: MapComponent },
{ path: '', redirectTo: '/map', pathMatch: 'full' },
];
styles.scss
body {
height: 100vh;
width: 100wh;
margin: 0;
}
angular.json
by adding node_modules/leaflet/dist/leaflet.css
to styles
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"leaflet-angular-example": {
// ...
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
// ...
"styles": [
"src/styles.scss",
"node_modules/leaflet/dist/leaflet.css" // <-- add this line
],
// ...
map.component.html
<div id="map" #map>
</div>
map.component.scss
#map {
height: 100vh;
width: 100vw;
}
map.component.ts
import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';
import { Map, map, tileLayer } from 'leaflet';
@Component({
selector: 'app-map',
standalone: true,
imports: [],
templateUrl: './map.component.html',
styleUrl: './map.component.scss'
})
export class MapComponent implements AfterViewInit {
@ViewChild('map')
mapElementRef: ElementRef = null!;
private _map: Map = null!;
ngAfterViewInit(): void {
this._map = map(this.mapElementRef.nativeElement)
.setView([46.801111, 8.226667], 8);
tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
// add a link to OpenStreetMap (omitted here for shorter line width)
attribution: '© OpenStreetMap'
}).addTo(this._map);
}
}