Search code examples
javascripthtmlleafletgeojson

Leaflet: How to fetch geojson from URL and pass it to L.geoJson


I try to load a geojson from an URL and display it in a map with leaflet:

<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/dist/leaflet.css"/>
    <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
</head>

<body>
<div id="my_map" style="height: 600px"></div>
<script>
const map = L.map('my_map')
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
map.setView([37.8, -96], 4);
async function load_shapefile() {
    let url = 'https://raw.githubusercontent.com/shawnbot/topogram/master/data/us-states.geojson';
    let shape_obj = await (await fetch(url)).json();
    return shape_obj
}
L.geoJson(load_shapefile()).addTo(map);
</script>
</body>
</html>

I get on the JS Console:

Uncaught Error: Invalid GeoJSON object.
    at De (GeoJSON.js:221)
    at i.addData (GeoJSON.js:117)
    at initialize (GeoJSON.js:92)
    at new i (Class.js:22)
    at Object.Ke (GeoJSON.js:439)
    at leaflet.html:21

If possible, I would like to not use jQuery. Thanks for any input!

EDIT: I replaced the url with an actual GeoJSON file, thanks @IvanSanchez!


Solution

  • If you want to extract the geojson and use it later you need to create another function to await the result as the operation is asynchornous:

    <html>
    
    <head>
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
      <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
    </head>
    
    <body>
      <div id="my_map" style="height: 600px"></div>
      <script>
        const map = L.map('my_map')
        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
        map.setView([37.8, -96], 4);
    
        async function load_shapefile() {
          let url = 'https://raw.githubusercontent.com/shawnbot/topogram/master/data/us-states.geojson';
          const response = await fetch(url)
          const shape_obj = await response.json();
          console.log(shape_obj);
          return shape_obj;
        }
    
        async function main() {
          const json = await load_shapefile();
          L.geoJson(json).addTo(map);
        }
    
        main();
      </script>
    </body>
    
    </html>

    Otherwise if you do not want to use the geojson instance further use then to fetch the data and immediately use them.

    <html>
    
    <head>
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
      <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
    </head>
    
    <body>
      <div id="my_map" style="height: 600px"></div>
      <script>
        const map = L.map('my_map')
        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
        map.setView([37.8, -96], 4);
    
        let url = 'https://raw.githubusercontent.com/shawnbot/topogram/master/data/us-states.geojson';
        const response = fetch(url).then(response => response.json()).then(response => {
          L.geoJson(response).addTo(map);
        })
      </script>
    </body>
    
    </html>