3

I'm loading a GeoJSON layer in Leaflet, and would like to be able to change the properties of each feature by using a box in the feature's popup. When the feature's property changes, I'd like to change the style of the feature as well.

I'm sure this is possible- I've read several change style/property questions, and several javascript-in-popups questions, but just can't seem to get it right.

Here's a JS Fiddle: http://jsfiddle.net/quu3ykp6/7/

Desired workflow is as follows: user clicks a feature, changes the box in the popup, this calls a javascript function that changes the style and properties of the feature in question.

1 Answer 1

6

From the code you provide in your JSFiddle:

function onEachFeature(feature, layer) {

  var popup = '<select name="select" onchange="restyleLayer(this.value)">'
  popup += '<option value="Nope" selected>None</option>'
  popup += '<option value="Democrat">Democrat</option>'
  popup += '<option value="Republican">Republican</option>'
  popup += '</select>'
  layer.bindPopup(popup);

}

=> JSFiddle does not like inline JavaScript. If you open your browser console and change a popup select, it will throw a message stating "restyleLayer is not defined".

Instead, you should create HTMLElements, fill the <option>'s value and innerHTML, append them to your <select>, and attach an event listener to that <select>:

function onEachFeature(feature, layer) {

  var select = document.createElement('select'),
    option0 = document.createElement('option'),
    option1 = document.createElement('option'),
    option2 = document.createElement('option');

  select.addEventListener('change', function() {
    restyleLayer(this.value, this.layer);
  });

  select.layer = layer;

  option0.value = 'Nope';
  option0.selected = true;
  option0.innerHTML = 'None';

  option1.value = 'Democrat';
  option1.innerHTML = 'Democrat';

  option2.value = 'Republican';
  option2.innerHTML = 'Republican';

  select.appendChild(option0);
  select.appendChild(option1);
  select.appendChild(option2);

  layer.bindPopup(select);

}

Then:

function restyleLayer(party) {

  states_geojson.eachLayer(function(layer) {

    // update the actual layer to the property from the select
    layer.feature.properties.party = party;

    var myFillColor = getColor(party);

    layer.setStyle({
      fillColor: myFillColor
    });
  });
}

When you change the select value for one of your polygons, you apply the change to each layer of your states_geojson GeoJSON layer group. This is very probably not what you are trying to achieve, which is most probably to change the party only for the polygon with open popup. So you should pass the current layer as another argument of your restyleLayer function.

Furthermore:

function getColor(party) {
  console.log(party)
  switch (party) {
    case 'Republican':
      return {
        color: "#ff0000"
      };
    case 'Democrat':
      return {
        color: "#0000ff"
      };
    case 'Nope':
      return {
        color: 'grey'
      };
  }
}

Your getColor function returns an object, not a simple color as string. Therefore:

var myFillColor = getColor(party);

layer.setStyle({
  fillColor: myFillColor
});

…is incorrect, as it ends up with something like:

layer.setStyle({
  fillColor: {
      color: "#0000ff"
  }
});

So instead you just need:

layer.setStyle(myFillColor);

For example:

function restyleLayer(party, layer) {

  layer.feature.properties.party = party;

  var myFillColor = getColor(party);

  layer.setStyle(myFillColor);
}

Updated JSFiddle: http://jsfiddle.net/quu3ykp6/9/

1
  • thank you so much for your help-- definitely improves my understanding of javascript, html and leaflet. Thank you! Mar 20, 2017 at 13:08

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.