Search code examples
javascriptjqueryjquery-uileafletgeojson

Zoom after search using autocomplete


How to do after a search, zoom in on the value found on the map? My code is:

$("#txtSearch").autocomplete({
    source: setoresComerciais.features.map(function(d){
        return d.properties.sco_num_sc + " - " + d.properties.sco_dsc_loc
    }),
    select: function(event, ui){
        map.fitBounds(stComerciaisLayer.getBounds(ui.item.value));
    } 
});

First, I get return d.properties.sco_num_sc + " - " + d.properties.sco_dsc_loc, this return, for example: "1 - FORTALEZA" After, I use select, where have the param ui, when do ui.item.value return "1 - FORTALEZA", so this:

map.fitBounds(stComerciaisLayer.getBounds(ui.item.value));

Where:

stComerciaisLayer = L.geoJSON(setoresComerciais, {
                style: function (feature) {
                    return feature.properties && feature.properties.style;
                },
                onEachFeature: onEachFeature,
(...)

It was to return exactly what I wanted, the result of the search and the zoom in it, but don't work. What did I do wrong?


Solution

  • This line:

    map.fitBounds(stComerciaisLayer.getBounds(ui.item.value));
    

    won't work as intended. From the API documentation, getBounds() doesn't take any arguments, it just returns the bounds of they layer you are working with. As the layer includes all your geojson, this won't work.

    Instead, we can get the selected feature's geojson from your geojson FeatureCollection, and from that make a layer (we don't need to add it to the map), so that we can find its bounds and update the map accordingly.

    How do we get the proper feature in the geojson? There are a few approaches, we could use a dictionary, or we could add additional data to the autocomplete function source (as suggested in the other answer). I'll follow the lead in the other answer, but use the increment of the feature and continue to use .map() :

    source: setoresComerciais.features.map(function(d,i){
        return {
          label: d.properties.sco_num_sc + " - " + d.properties.sco_dsc_loc, 
          id: i 
        };
    

    Here .map takes two variables: d is the current item in the features array being processed, and i is the index of that feature. With the index, we can easily access the proper item in the features array, make a layer out of it, and fit the map bounds to that feature's layer:

    select: function(event, ui){
        var feature = setoresComerciais.features[ui.item.id]; // get the geojson
        var featureLayer = L.geoJSON(feature)  // create a layer from it
        map.fitBounds(featureLayer.getBounds()); // resize the map
    } 
    

    Altogether, that gives us:

        $("#txtSearch").autocomplete({
            source: setoresComerciais.features.map(function(d,i){
                return {label: d.properties.sco_num_sc + " - " + d.properties.sco_dsc_loc, id: i };
            }),
            select: function(event, ui){
                var feature = setoresComerciais.features[ui.item.id];
                var featureLayer = L.geoJSON(feature)
                map.fitBounds(featureLayer.getBounds());
            } 
        });