2

I'm new to Leaflet and Javascript. I've been working through various tutorials to try and produce what I need but I'm missing something.

Essentially I would like to produce a Leaflet map with a drop down selector that changes the styling and popups of my GeoJSON based on different attributes.

Here is my code:

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

    map.dragging.disable();
    map.touchZoom.disable();
    map.doubleClickZoom.disable();
    map.scrollWheelZoom.disable();
    map.boxZoom.disable();
    map.keyboard.disable();

    // Create control for dropdown selector

    var selector = L.control({
        position: 'topright'
    });

    // Add content to the control

    selector.onAdd = function(map) {

    //create div container  

    var div = L.DomUtil.create('div', 'hazard_select');

    //create select element within container (with id, so it can be referred to later
    div.innerHTML = '<select id="hazard_select"><option value ="FL">River flood</option><option value ="EQ">Earthquake</option><option value ="DR">Water scarcity</option><option value ="CY">Cyclone</option><option value ="CF">Coastal flood</option><option value ="TS">Tsunami</option><option value ="VO">Volcano</option><option value ="LS">Landslide</option></select>';
      return div; 
   
    };

    // Add the selector to the map
     selector.addTo(map);

    var geojson, style_change, hazard;

    // Define a style

    function restylemap(feature, hazard) {


      if (feature.properties.FL_SUB !== null) {
          return {
          weight: 1.2,
          color: '#0072bc',
          fillColor: '#08519c',
          lineJoin: 'bevel',
          opacity: 1.0,
          fillOpacity: 1.0
          };
      }
      else if (feature.properties.FL_NAT !== null) {
          return {
          weight: 1.2,
          color: '#659ad2',
          fillColor: '#3182bd',
          lineJoin: 'bevel',
          opacity: 1.0,
          fillOpacity: 1.0
          };
      } 
      else if (feature.properties.FL_REG !== null) {
          return {
          weight: 1.2,
          color: '#659ad2',
          fillColor: '#6baed6',
          lineJoin: 'bevel',
          opacity: 1.0,
          fillOpacity: 1.0
          };
      } 
      else {
          return {
          weight: 1,
          color: '#afafaf',
          fillColor: '#bdd7e7',
          lineJoin: 'bevel',
          opacity: 1.0,
          fillOpacity: 1.0
          };
      }
        
    }

    // Get json through jquery

    $.getJSON("js/dataholdings.geojson", function(data) {
    geojson = L.geoJson(data, {
      style: restylemap,
      onEachFeature: function (feature, layer) {
       layer.bindPopup("Name: " + feature.properties.ADM0_NAME);
      },
      
    });

    // Add event listeners


    style_change = L.DomUtil.get("hazard_select");
    L.DomEvent.addListener(style_change, 'click', function(e) {
      L.DomEvent.stopPropagation(e);
    });

    L.DomEvent.addListener(style_change, 'change', changeHandler);


    function changeHandler(e) {
      geojson = L.geoJson(data,
      restylemap(geojson,e.target.value)  
      )
    }
 

    map.fitBounds(geojson.getBounds()); 
    geojson.addTo(map);
    });

This works to initially style the map, but not when the drop down is changed. I think the problem is with my changeHandler function, it passes on the Hazard ID to restylemap but then has the error "TypeError: undefined is not an object (evaluating 'feature.properties.FL_SUB')". As hazard is replacing feature?

I wanted to pass the Hazard variable into the 'Feature.properties' somehow i.e (feature.properties[hazard]& '_REG' !== null).

Would this work?

1 Answer 1

2

You guessed almost right, your restylemap function does not like receiving geojson,e.target.value as arguments, instead of its specified feature, hazard signature (where actually just feature is used).

So your error comes from passing geojson full Leaflet layer group in place of the expected feature plain single GeoJSON feature object. It tries to read the properties key of your geojson argument, but finds none, so it is undefined ("not an object"). Then it tries to read the FL_SUB key, but there is no key on undefined.

Furthermore, within your select change listener changeHandler, you re-assign your geojson variable but do not add it to map. Therefore it would duplicate your layers, without actually adding the new ones to the map.

For the above issue, you should rather use the .setStyle() method on your geojson variable within changeHandler instead of creating a new layer through L.geoJson.

Then you are left with specifying a new style function that depends on your select (drop-down) chosen value. For this, you should realize that you may need an array of styling functions, or a function that works on a 2-dimensional scale, since you seem to need 2 variables (your selected value and the layers feature properties). In your current restylemap, you use only the layers feature properties.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.