Search code examples
javascriptleafletprototypal-inheritance

Using Prototypal Pattern with Creating a Leaflet Map: error with onEachFeature function


I have the following code that I call to create a copy object of map, and initialize the Leaflet map. This works and loads properly. However, the onEachFeature and/or the clickFeature functions are not working properly.

var map = {
    mapUrl: "",
    maxZoom: 18,
    minZoom: 2,
    map: L.map('worldMap').setView([51.505, -0.09], 2),
    create: function(values) {
        var instance = Object.create(this);
        Object.keys(values).forEach(function(key) {
        instance[key] = values[key];
        });
        return instance;
    },
    initLeafletMap: function() {
        L.tileLayer(this.mapUrl, {
            attribution: '',
            maxZoom: this.maxZoom,
            minZoom: this.minZoom,
            id: 'mapbox.streets'
        }).addTo(this.map);
        //add continents' outlines
        $.getJSON("/static/continents.json", 
           (function(style, onEachFeature, map) {
                return function(continents) {
                    console.log(typeof(continents));
                    L.geoJson(continents, {
                        style: style,
                        onEachFeature: onEachFeature
                    }).addTo(map);
                };
            }(this.style, this.onEachFeature, this.map))
       );
    },
    style: function() {
        return {
            weight: 2,
            opacity: 1,
            color: 'beige',
            dashArray: '3',
            fillOpacity: 0
        };
    },
    onEachFeature: function(feature, layer) {
        layer.on({
            click: this.clickFeature
        });
    },
    clickFeature: function(e) {
            do something here();
    },

So when I click on the map, I know the onEachFeature function is called, but it does not call clickFeature. Instead I get this error in the console:

leaflet.js:5 Uncaught TypeError: Cannot read property 'call' of undefined
    at e.fire (leaflet.js:5)
    at e._fireDOMEvent (leaflet.js:5)
    at e._handleDOMEvent (leaflet.js:5)
    at HTMLDivElement.r (leaflet.js:5)

Solution

  • Much probably simply need to bind the this context when you pass your onEachFeature method as argument of your IIFE to build the callback to your AJAX call:

    this.onEachFeature.bind(this)
    

    See also Leaflet- marker click event works fine but methods of the class are undefined in the callback function

    BTW you could also attach your click event listener directly on the Leaflet GeoJSON Layer Group instead of doing it for each child layer.