4
\$\begingroup\$

I am trying to render in a leaflet map that should render a single marker. I am building the JavaScript as follows.

  1. build the map
  2. an even listener for when the user opens the page where the map is rendered.

I query as follows:

@company = Company.friendly.find_by(
                        slug: [ params[:id],
                        params[:company_id] ])
respond_to do |format|
      format.html
      format.json { render json:
        {
          type: "Feature",
          "geometry": {
            "type": "Point",
            "coordinates": [@company.longitude, @company.latitude] # this part is tricky
          },
          properties: {
            "title": @company.name,
            "address": @company.street_address,
          }
        }
      }
    end

I console log the steps and everything seems to "work". The data is loaded and data.responseJSON renders as follows:

geometry: {…}
​​coordinates: Array [ 1.5918642, 43.7189496 ]​​
type: "Point"
<prototype>: Object { … }
properties: Object { title: "Acme SaS", address: "xxx", "marker-color": "#FFFFFF", … }
type: "Feature"

However, the map does not ​render as wanted. Only a grey box shows up. If I provide with a lat, Lon array, the map renders a map.

function buildCompanyMap() {

  document.getElementById('company_map').innerHTML = "<div id='map' style='width: 100%; height: 100%;'></div>";

  console.log("script #1: %o", document.getElementById('company_map'));
  console.log("script #2: %o", document.getElementById('map'));

  var data = $.ajax({
      url: "#companies/company.json",
      dataType: "json",
      success: console.log("company data successfully loaded."),
      error: function(xhr) {
          alert(xhr.statusText)
      }
  });

  console.log("script #3: %o", $);

  console.log("script #4: %o", data);

  $.when(data).done(function() {
    var map = new L.Map('map', {
        dragging: false,
        tap: false,
        scrollWheelZoom: false
      });

    var osmUrl = 'https://{s}.tile.osm.org/{z}/{x}/{y}.png',
        osmAttribution = 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors,' +
                        ' <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
        osmLayer = new L.TileLayer(osmUrl, {maxZoom: 18, attribution: osmAttribution});

    map.addLayer(osmLayer);

    console.log("script #5: %o", data.responseJSON);

    var geojsonMarkerOptions = {
        radius: 8,
        fillColor: "#ff7800",
        color: "#000",
        weight: 1,
        opacity: 1,
        fillOpacity: 0.8
    };

    L.geoJSON(data.responseJSON, {
        pointToLayer: function (feature, latlng) {
            return L.circleMarker(latlng, geojsonMarkerOptions);
        }
    }).addTo(map);

  });
};

document.addEventListener("turbolinks:load", function() {
  if (document.getElementById('company_map') == null) {
    //console.log('true')
  }
  else {
    buildCompanyMap();
  }
});
\$\endgroup\$
2
\$\begingroup\$

A correction. I have removed the use of jQuery in the correction. The main issue was that you don't set anywhere a map center and a zoom. I've changed the behaviour by zooming the map to GeoJSON extent (e.g map.fitBounds(jsonLayer.getBounds());)

You could also made the change by setting a map center and a zoom like described in this link to official doc.

function buildCompanyMap() {

  document.getElementById('company_map').innerHTML = "<div id='map' style='width: 100%; height: 100%;'></div>";

  console.log("script #1: %o", document.getElementById('company_map'));
  console.log("script #2: %o", document.getElementById('map'));

  var map = new L.Map('map', {
      dragging: false,
      tap: false,
      scrollWheelZoom: false
    });

  var osmUrl = 'https://{s}.tile.osm.org/{z}/{x}/{y}.png',
      osmAttribution = 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors,' +
                      ' <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
      osmLayer = new L.TileLayer(osmUrl, {maxZoom: 18, attribution: osmAttribution});

  map.addLayer(osmLayer);

  console.log("script #5: %o", data.responseJSON);

  var geojsonMarkerOptions = {
      radius: 8,
      fillColor: "#ff7800",
      color: "#000",
      weight: 1,
      opacity: 1,
      fillOpacity: 0.8
  };

  fetch('#companies/company.json', {
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      }
    })
    .then(response => response.json())
    .then (json => {
      var jsonLayer = L.geoJSON(json, {
        pointToLayer: function (feature, latlng) {
            return L.circleMarker(latlng, geojsonMarkerOptions);
        }
      })
      jsonLayer.addTo(map);
      map.fitBounds(jsonLayer.getBounds());
    })
    .catch(function(error) {
      console.log('Error on fetch operation: ' + error.message);
    });

};

document.addEventListener("turbolinks:load", function() {
  if (document.getElementById('company_map') == null) {
    //console.log('true')
  }
  else {
    buildCompanyMap();
  }
});

\$\endgroup\$
5
  • \$\begingroup\$ Thanks. I might have an issue with my formatting on the son response as I get: "Uncaught (in promise) SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data" \$\endgroup\$
    – Thierry
    Jul 16 '20 at 18:46
  • \$\begingroup\$ Copy the content of your returned GeoJSON to geojsonlint.com. It validates you are using GeoJSON \$\endgroup\$
    – ThomasG77
    Jul 16 '20 at 18:55
  • \$\begingroup\$ well, it's valid geojson When I modify the map var and add a set view on dummy data, the map will render o the coordinates. var map = new L.Map('map', { dragging: false, tap: false, scrollWheelZoom: false }).setView([39.045753, -76.641273], 9); \$\endgroup\$
    – Thierry
    Jul 16 '20 at 19:02
  • \$\begingroup\$ Yes but without the GeoJSON. It's the issue here. Made some changes in the fetch (adding headers to explicitly ask for JSON output and catch statement to help debug error) \$\endgroup\$
    – ThomasG77
    Jul 16 '20 at 19:25
  • \$\begingroup\$ You got it solved. Thanks a bunch. So the solution was to be be explicit by adding headers. \$\endgroup\$
    – Thierry
    Jul 16 '20 at 19:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy