leafletgeocoderleaflet-routing-machineesri-leaflet-geocoder

How to add predefined places/markers to Leaflet Geocoder


I am using Leaflet Map with geocoder (ESRI) and Routing Machine. I have added two markers, let's say my home and my work

var marker_work = L.marker([50.27, 19.03], { title: 'MyWork'}).addTo(map)
.bindPopup("work").openPopup();

var marker_home = L.marker([50.10, 18.4], { title: 'MyHome'}).addTo(map)
.bindPopup("home").openPopup();

Here is an example fiddle: https://jsfiddle.net/21nmk8so/1/

How can I add this markers/point as a predefined places for ControlGeocoder? I want to use them in search and use as a start point / end point for route calculation.

Another example for the same question: how to add custom-fake city with lat/lon and be able to search (find route) to/from that city.


Solution

  • I don't know if this is the best solution but it is working: Create a custom Geocoder Class which overwrites the geocode function. There you can overwrite the result function and apply suggestions to the result.

    L.CustomGeocoder = L.Control.Geocoder.Nominatim.extend({
        suggestions: [],
        setSuggestions(arr){
          this.suggestions = arr;
        },
        createSuggestionFromMarker(marker){
          this.suggestions.push({name: marker.options.title, center: marker.getLatLng()});
        },
        getResultsOfSuggestions(query){
          var results = [];
          this.suggestions.forEach((point)=>{
            if(point.name.indexOf(query) > -1){
              point.center = L.latLng(point.center);
              point.bbox = point.center.toBounds(100);
              results.push(point);
            }
          });
          return results;
        },
        geocode(query, resultFnc, context) {
          var that = this;
          var callback = function(results){
            var sugg = that.getResultsOfSuggestions(query);
            resultFnc.call(this,sugg.concat(results));
          }
          L.Control.Geocoder.Nominatim.prototype.geocode.call(that,query, callback, context);
        }
      })
    

    Then you have to use the new Geocoder Class:

    var geocoder = new L.CustomGeocoder({});
    
    var control = L.Routing.control({
      waypoints: [],
      router: new L.Routing.osrmv1({
        language: 'en',
        profile: 'car'
      }),
      geocoder: geocoder
    }).addTo(map);
    

    And finally you can add suggestions over markers and theier title option over createSuggestionFromMarker(marker) or setSuggestions(arr):

    var suggestions = [
      {
        name: 'Test Car 1',
        center: [50.27, 19.03]
      },
      {
        name: 'Test Car 2',
        center: [50.10, 18.4]
      }
    ];
    geocoder.setSuggestions(suggestions);
    
    var marker_work = L.marker([50.27, 19.03], { title: 'MyWork'}).addTo(map);
    var marker_home = L.marker([50.10, 18.4], { title: 'MyHome'}).addTo(map);
    
    geocoder.createSuggestionFromMarker(marker_work);
    geocoder.createSuggestionFromMarker(marker_home);
    

    Update, use marker Ref instead of fix latlng

    Change this two function, then the marker is referenced and it always searches from the current position of the marker:

    
        createSuggestionFromMarker(marker){
          this.suggestions.push({name: marker.options.title, marker: marker});
        },
        getResultsOfSuggestions(query){
          var results = [];
          this.suggestions.forEach((point)=>{
            if(point.name.indexOf(query) > -1){
                if(point.marker){
                point.center = point.marker.getLatLng();
              }
              point.center = L.latLng(point.center);
              point.bbox = point.center.toBounds(100);
              results.push(point);
            }
          });
          return results;
        },
    

    You can test this in the demo, when you drag the marker

    https://jsfiddle.net/falkedesign/hu25jfd1/