Leaflet – How to Search for Point Types Using Leaflet Search and JavaScript

geojsonjavascriptleaflet

I followed this repository Leaflet Search

and I want to combine search box, using polygons, polylines, and point.
for polygons and polylines is working fine. But not for points. The property Name does appear but, when I select it there is no response..

error

as you can see i got error when i find point

and if i find anothers likes Polylines or polygons, the results was successfull

<script src="data/us-states.js"></script>
    <script src="data/restaurant.geojson.js"></script>

var map = new L.Map('map', {zoom: 1, center: new L.latLng([37.8, -96]) });

    map.addLayer(new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png')); //base layer

    var us_states = new L.GeoJSON(us_states, {
        style: function(feature) {
            return {color: feature.properties.color };
        },
        onEachFeature: function(feature, marker) {
            marker.bindPopup('<h4 style="color:'+feature.properties.color+'">'+ feature.properties.name +'</h4>');
        }
    });

    map.addLayer(us_states);

    var restaurant = new L.GeoJSON(restaurant, {
        style: function(feature) {
            return {color: feature.properties.color };
        },
        onEachFeature: function(feature, marker) {
            marker.bindPopup('<h4 style="color:'+feature.properties.color+'">'+ feature.properties.name +'</h4>');
        }
    });

    map.addLayer(restaurant);

    var searchControl = new L.Control.Search({
        layer: L.featureGroup([us_states,restaurant]),
        propertyName: 'name',
        marker: false,
        moveToLocation: function(latlng, title, map) {
            var zoom = map.getBoundsZoom(latlng.layer.getBounds());
            map.setView(latlng, zoom); 
        }
    });

    searchControl.on('search:locationfound', function(e) {
        e.layer.setStyle({fillColor: '#3f0', color: '#0f0'});
        if(e.layer._popup)
            e.layer.openPopup();

    }).on('search:collapsed', function(e) {

        featuresLayer.eachLayer(function(layer) {
            featuresLayer.resetStyle(layer);
        }); 
    });

    map.addControl( searchControl );  

maybe someone can help me?

this error notice :

Uncaught TypeError: latlng.layer.getBounds is not a function
at e.moveToLocation [as _moveToLocation] (geojson-layer.html:63)
at e.showLocation (leaflet-search.js:893)
at e._handleSubmit (leaflet-search.js:856)
at e. (leaflet-search.js:398)
at HTMLLIElement.r (leaflet.js:5)

Best Answer

Problematic code seems to be mixture of two Leaflet Search examples: geojson-layer and multiple-layers.

First problem is that there was some renaming done but not completely. Original layer featuresLayer is now us_states, but in search:collapsed event handler there is still old name.

The secend problem is that in restaurant geojson features have Point geometry and have to be treated differently from us_states geojson, where features have Polygon geometry.

Difference has to accounted for in layer definition (onEachFeature for polygons, pointToLayer for points), in moveToLocation option of search control definition and in search:locationfound event handler.

var map = new L.Map('map', {zoom: 1, center: new L.latLng([37.8, -96]) });

map.addLayer(new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png')); //base layer

var us_statesLayer = new L.GeoJSON(us_states, {
        style: function(feature) {
            return {color: feature.properties.color };
        },
        onEachFeature: function(feature, marker) {
            marker.bindPopup('<h4 style="color:'+feature.properties.color+'">'+ feature.properties.name +'</h4>');
        }
    });

var restaurantLayer = new L.GeoJSON(restaurant, {
        pointToLayer: function(feature, latlng) {
            return L.marker(latlng, {
                icon: L.divIcon({
                    className: feature.properties.amenity,
                    iconSize: L.point(16, 16),
                    html: feature.properties.amenity[0].toUpperCase(),
                })
            }).bindPopup(feature.properties.amenity+'<br><b>'+feature.properties.name+'</b>');
        }
});

var allLayers = L.layerGroup([
    us_statesLayer,
    restaurantLayer
])

map.addLayer(allLayers);

var lastStateLayerFound = null;

var searchControl = new L.Control.Search({
    layer: allLayers,
    propertyName: 'name',
    marker: false,
    moveToLocation: function(latlng, title, map) {
        var zoom;
        if (latlng.layer.feature.geometry.type == 'Polygon') {
          zoom = map.getBoundsZoom(latlng.layer.getBounds());
          lastStateLayerFound = latlng.layer;
          }
        else {
          lastStateLayerFound = null;
          zoom = 15;
        }
        map.setView(latlng, zoom);
    }
});

searchControl.on('search:locationfound', function(e) {
    if (e.layer.feature.geometry.type == 'Polygon')
      e.layer.setStyle({fillColor: '#3f0', color: '#0f0'});       
    if(e.layer._popup)
        e.layer.openPopup();

}).on('search:collapsed', function(e) {
    if (lastStateLayerFound) {
      us_statesLayer.resetStyle(lastStateLayerFound);
    }
});

map.addControl(searchControl);