I am trying to add a legend to a map created by Asymmetrik/ngx-leaflet. The map is created by following the tutorial in https://github.com/Asymmetrik/ngx-leaflet . There are two different layers and for each layer there shoud be a different legend. The code is made by using angular CLI and leaflet. There is a map component. The map.component.ts file is as follows:
import {Component, Input, OnChanges, OnInit} from '@angular/core';
import {circle, geoJSON, GeoJSONOptions, latLng, Layer, LeafletMouseEvent, polygon, tileLayer} from 'leaflet';
import * as L from 'leaflet';
import {SimpleResult} from '../../models/SimpleResult';
import {HttpClient} from '@angular/common/http';
import {IDrilldownResult} from '../../models/DrilldownResult';
@Component({
selector: 'app-map-chart',
templateUrl: './map-chart.component.html',
styleUrls: ['./map-chart.component.css']
})
export class MapChartComponent implements OnInit, OnChanges {
@Input() private data: IDrilldownResult;
public options: any;
public layersControl = {
baseLayers: { }
};
private getColor(value, max, min) {
const val = (value - min) / (max - min) ;
const hue = (val * 120).toString(10);
return ['hsl(', hue, ',100%,50%)'].join('');
}
constructor(
private http: HttpClient
) { }
ngOnInit() {
this.createChart();
/*if (this.data) {
this.updateChart();
}*/
}
ngOnChanges() {
this.updateChart();
}
private createChart() {
this.options = {
layers: [
tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18, attribution: '...' }),
],
zoom: 6,
center: latLng(51.5167, 9.9167)
};
}
private createGermanyLayer() {
this.http.get('assets/bundeslaender.geojson')
.subscribe((res: any) => {
const deIndex = this.data.children.findIndex(e => e.name === 'de');
const germanData = this.data.children[deIndex];
res.features.forEach(feat => {
const stateIndex = germanData.children.findIndex(e => {
if (e.name) {
return e.name.toLowerCase() === feat.properties.NAME_1.toLowerCase();
}
});
feat.properties.SALES = germanData.children[stateIndex].label;
});
const max = Math.max.apply(Math, res.features.map(feat => feat.properties.SALES));
const min = Math.min.apply(Math, res.features.map(feat => feat.properties.SALES));
const geoJsonGermanyLayer = {
id: 'geoJSON',
name: 'Geo JSON Polygon',
enabled: true,
layer: geoJSON(
res as any,
{
style: (d) => {
const color = this.getColor(d.properties.SALES, max, min);
return ({
color: color,
weight: 1
});
},
onEachFeature: (feature, layer) => {
layer.bindPopup('<h5>' + feature.properties.NAME_1 + '</h5><p>Revenue: ' + feature.properties.SALES.toFixed(2) + '</p>');
}
})
};
this.layersControl.baseLayers['Germany'] = geoJsonGermanyLayer.layer;
// begining of legend
const v1 = min;
const v2 = min + Math.round((max - min ) / 2);
const v3 = max;
const legend = new (L.Control.extend({
options: { position: 'bottomright' }
}));
// const legend = L.control({position: 'bottomright'});
const vm = this;
legend.onAdd = function (map) {
const div = L.DomUtil.create('div', 'legend');
const labels = [
'Sales greater than ' + v1,
'Sales greater than ' + v2,
'Sales equal or less than ' + v3
];
const grades = [v1 + 1, v2 + 1, v3 ];
div.innerHTML = '<div><b>Legend</b></div>';
for (let i = 0; i < grades.length; i++) {
div.innerHTML += '<i style="background:' + vm.getColor(grades[ i ], this.max, this.min) + '"> </i> '
+ labels[i] + '<br/>';
}
return div;
};
legend.addTo(geoJsonGermanyLayer);
// end of legend
});
}
private createEuropeLayer() {
this.http.get('assets/europe.geojson')
.subscribe((res: any) => {
res.features.forEach(feat => {
const countryIndex = this.data.children.findIndex(e => {
if (e.name) {
return e.name.toLowerCase() === feat.properties.FIPS.toLowerCase() || e.name.toLowerCase() === feat.properties.ISO2.toLowerCase();
}
});
feat.properties.SALES = countryIndex !== -1 ? this.data.children[countryIndex].label : undefined;
});
const max = Math.max.apply(Math, res.features.filter(feat => feat.properties.SALES !== undefined).map(feat => feat.properties.SALES));
const min = Math.min.apply(Math, res.features.filter(feat => feat.properties.SALES !== undefined).map(feat => feat.properties.SALES));
const maxLog = Math.log(max);
const minLog = Math.log(min);
const geoJsonEuropeLayer = {
id: 'geoJSON',
name: 'Geo JSON Polygon',
enabled: true,
layer: geoJSON(
res as any,
{
style: (d) => {
const color = this.getColor(Math.log(d.properties.SALES), maxLog, minLog);
return ({
color: color,
weight: 1
});
},
onEachFeature: (feature, layer) => {
const sales = feature.properties.SALES !== undefined ? feature.properties.SALES.toFixed(2) : 'No orders';
layer.bindPopup('<h5>' + feature.properties.NAME + '</h5>' +
'<p>Revenue: ' + sales + '</p>');
}
})
};
this.layersControl.baseLayers['Europe'] = geoJsonEuropeLayer.layer;
});
}
private updateChart() {
this.createGermanyLayer();
this.createEuropeLayer();
}
}
The legend does not appear on the page. The console shows the follwoing error: cannot read property 'bottomright' of undefined as shown in the image below:
The map is shown correctly but there is no legend. I appreciate if you tell me what is wrong with my code and why the legend is not showing. Thank you for your attention.