2

I have 2 identical layers overlapping, each containing identical FeatureCollection values. Only one of them is added into the map.

Is it possible that when clicking on a specific feature of the visible layer, to bring up the correspondant one from the other layer?

For the moment I am using the below but this brings up the entire layer, not just the desired feature.

 layer_tt2_0.on('click', function(ev) {
 layer_tt1_1.addTo(map)});

The features have separate ids. 1a, 1b etc. The same ID is present in both layers for the same features.

"features": [ { "type": "Feature", "properties": { "name": "1a" }, "geometry": { "type": "LineString", "coordinates": [[coordinates here]],

The code obtained with qgis2web is below, added TomazicM's suggestion as well. I'm receiving an error in the console "Uncaught TypeError: Cannot read property 'properties' of undefined" and I cannot identify the cause.

    var map = L.map('map', {
        zoomControl:true, maxZoom:28, minZoom:1
    }).fitBounds([[45.505788666842555,25.183138708143936],[45.620566687311815,25.392037287580678]]);
    var hash = new L.Hash(map);
    map.attributionControl.setPrefix('<a href="https://github.com/tomchadwin/qgis2web" target="_blank">qgis2web</a> &middot; <a href="https://leafletjs.com" title="A JS library for interactive maps">Leaflet</a> &middot; <a href="https://qgis.org">QGIS</a>');
    var autolinker = new Autolinker({truncate: {length: 30, location: 'smart'}});
    var bounds_group = new L.featureGroup([]);
    function setBounds() {
    }
    function pop_tt2_0(feature, layer) {
        var popupContent = '<table>\
                <tr>\
                    <td colspan="2">' + (feature.properties['name'] !== null ? autolinker.link(feature.properties['name'].toLocaleString()) : '') + '</td>\
                </tr>\
            </table>';
        layer.bindPopup(popupContent, {maxHeight: 400});
    }

    function style_tt2_0_0() {
        return {
            pane: 'pane_tt2_0',
            opacity: 1,
            color: 'rgba(125,139,143,1.0)',
            dashArray: '',
            lineCap: 'square',
            lineJoin: 'bevel',
            weight: 8.0,
            fillOpacity: 0,
            interactive: true,
        }
    }
    map.createPane('pane_tt2_0');
    map.getPane('pane_tt2_0').style.zIndex = 400;
    map.getPane('pane_tt2_0').style['mix-blend-mode'] = 'normal';
    var layer_tt2_0 = new L.geoJson(json_tt2_0, {
        attribution: '',
        interactive: true,
        dataVar: 'json_tt2_0',
        layerName: 'layer_tt2_0',
        pane: 'pane_tt2_0',
        onEachFeature: pop_tt2_0,
        style: style_tt2_0_0,
    });
    bounds_group.addLayer(layer_tt2_0);
    map.addLayer(layer_tt2_0);
    function pop_tt1_1(feature, layer) {
        var popupContent = '<table>\
                <tr>\
                    <td colspan="2">' + (feature.properties['name'] !== null ? autolinker.link(feature.properties['name'].toLocaleString()) : '') + '</td>\
                </tr>\
            </table>';
        layer.bindPopup(popupContent, {maxHeight: 400});
    }

    function style_tt1_1_0() {
        return {
            pane: 'pane_tt1_1',
            opacity: 1,
            color: 'rgba(133,182,111,1.0)',
            dashArray: '',
            lineCap: 'square',
            lineJoin: 'bevel',
            weight: 8.0,
            fillOpacity: 0,
            interactive: true,
        }
    }
    map.createPane('pane_tt1_1');
    map.getPane('pane_tt1_1').style.zIndex = 401;
    map.getPane('pane_tt1_1').style['mix-blend-mode'] = 'normal';
    var layer_tt1_1 = new L.geoJson(json_tt1_1, {
        attribution: '',
        interactive: true,
        dataVar: 'json_tt1_1',
        layerName: 'layer_tt1_1',
        pane: 'pane_tt1_1',
        onEachFeature: pop_tt1_1,
        style: style_tt1_1_0,
    });
    bounds_group.addLayer(layer_tt1_1);


    layer_tt2_0.on('click', function(ev) {
        var layer = ev.target;
        layer_tt1_1.eachLayer(function(layer2) {
            if (layer2.feature.properties.name == layer.feature.properties.name) {
                layer2.addTo(map);
            }
        });
    });


    setBounds();
0

1 Answer 1

2

Since GeoJSON layer is actually a group layer consisting of individual layers representing features, it's possible to add individual feature layer to the map, it just has to be identified by some id.

When clicking on the feature of the layer_tt2_0 layer, corresponding feature from the layer_tt1_1 is found with the help of group layer .eachLayer method, using feature property name.

In your case that could look something like this:

layer_tt2_0.on('click', function(ev) {
  var layer = ev.propagatedFrom;
  layer_tt1_1.eachLayer(function(layer2) {
    if (layer2.feature.properties.name == layer.feature.properties.name) {
      layer2.addTo(map);
    }
  });
});

Here is working JSFiddle (based on official Leaflet choropleth example): https://jsfiddle.net/TomazicM/bw5ymgda/

10
  • Thank you for your prompt reply. This makes a lot of sense, however when I'm running this, I receive an error in console"Cannot read property 'properties' of undefined" By running for example the below, works in getting the layer with the written ID, so there could be something with layer.feature.properties.name? Any ideas? layer_tt2_0.on('click', function(ev) { var layer = ev.target; layer_tt1_1.eachLayer(function(layer2) { if (layer2.feature.properties.name == "1a") { layer2.addTo(map); } }); });
    – AdriBu
    Commented May 22, 2020 at 19:04
  • 1
    Since I don't see your full relevant code I can't really say what's wrong. Code from the answer was tested on GeoJSON layers and it worked.
    – TomazicM
    Commented May 22, 2020 at 19:13
  • Thank you. I'll review everything on my end, most likely I missed something.
    – AdriBu
    Commented May 22, 2020 at 19:16
  • 1
    After another careful inspection I noticed that in my testing I was using click event processing on feature level, but you are using it on layer level. In this case to get the right feature layer in event processing function, event object property e.propagatedFrom has to be used. Answer is edited accordingly.
    – TomazicM
    Commented May 23, 2020 at 15:53
  • 1
    I added working JSFiddle example to the answer. It might help you finding the cause of your problem.
    – TomazicM
    Commented May 24, 2020 at 16:26

Your Answer

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

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