2

I'm adding some layers on a base map using OpenLayers. The aim is to create a layer with some features in it and later when user changes his prefered query, some other features need to be shown, so its the same layer but with different features. Therefore, I need to remove the layer and create it again with new features and then show it on the map.

I'm using the following code for defining and adding the layer:

var Selected_Buildings;
Selected_Buildings = new OpenLayers.Layer.Vector("MyLayer",  { eventListeners:{
            'featureselected':function(evt){        
//some actions here
            }, 
            'featureunselected':function(evt){
//some other actions here
            }},
        strategies: [new OpenLayers.Strategy.Fixed()],
            protocol: new OpenLayers.Protocol.HTTP({
                url: "url to php code that runs query and return geo-data in kml format",
                format: new OpenLayers.Format.KML({
                    extractStyles: false,
                    extractAttributes: true,
                    maxDepth: 2})
            }),
                styleMap: new OpenLayers.StyleMap({
                    "default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
                       strokeWidth: 2,
                     strokeColor: "Gold",
                     fillColor: "Gray"
                    }, OpenLayers.Feature.Vector.style["default"])),
                    "select": new OpenLayers.Style({
                     fillColor: "Blue"
                    })
                })
            });

And the code for defining SelectControl:

var selectControl;
selectControl = new OpenLayers.Control.SelectFeature(
                [Selected_Buildings],
                {
                    clickout: true, toggle: false,
                    multiple: false, hover: false
                }
            );
                map.addControl(selectControl);
                selectControl.activate();

and then when user clicks on a button, I try the following code for removing my layer and then again the above code is executed to add new layer:

var mLayers = map.layers;
var remLayers = [];

for (var i=0; i<mLayers.length; i++) {
    if (mLayers[i].name == "MyLayer") {
        remLayers.push(mLayers[i]);
    }
}

for (var i2=0; i2<remLayers.length; i2++) {
    map.removeLayer(remLayers[i2]);
}

map.removeControl(selectControl);

I receive no error, but also the layer is not removed from the base map. Any suggestion how to solve this problem?

In the above code MyLayer is the name of layer I would like to remove. selectControl is the name of the map control that was created before for the map.

Any help would be highly appreciated.

  • Hi, did you find a solution? – Tommaso Mar 31 '14 at 10:44
  • @Tommaso, I am back from a serious illness now, I will check the feedbacks from others and report back. – Catlover Aug 19 '14 at 10:26
1

The provided example works if the SelectControl is created with a Layer, not with an array of Layer:

var selectControl;
selectControl = new OpenLayers.Control.SelectFeature(
    Selected_Buildings,
    {
        clickout: true, toggle: false,
        multiple: false, hover: false
    }
 );
 map.addControl(selectControl);
 selectControl.activate();

Final answer

There is an an open bug with the SelectFeature control used on multiple layers: the control creates a "root" layer with a copy of the rendered features, so when you remove a layer from the map, the features are still visible on the map, since you are not removing the "hidden" root layer.

I didn't understand very well your use-case, but I think that there are 2 possible solutions:

  1. You can apply the patch proposed by the link above (it's easier to patch OpenLayers.debug.js, or you can build your own version of OL)
  2. You can use something like the following workaround (I understood that you have multiple kml layers on which you want the user to perform a select, I didn't understand if the user can remove only one of them, or all together....):

var pippo = new OpenLayers.Layer.Vector(...); // Layer1
var pluto = new OpenLayers.Layer.Vector(...); // Layer2
map.addLayers([pippo, pluto]);

// Creates the control on all the layers, activate and add it to the map 
selectControl = new OpenLayers.Control.SelectFeature([pippo, pluto]); 
map.addControl(selectControl);
selectControl.activate()

Then, to remove a layer, remove first the selectControl, then the layer

function removeLayer(layer) {

    // remove the control
    selectControl.deactivate();
    map.removeControl(selectControl);
    selectControl.destroy();

    // remove one layer
    map.removeLayer(pippo);

    // Re-create the control with the other layers or wathever
    selectControl = new OpenLayers.Control.SelectFeature(pluto);
    map.addControl(selectControl);
    selectControl.activate();

}
  • I have updated the question. Do you have any suggestions on how to fix this? – Catlover Mar 24 '14 at 13:15
  • If you crete the control with a single layer instead of an array, it works. – Tommaso Mar 24 '14 at 15:31
  • Thank you for your response. But I have another layer like this layer. Therefore I need to create one selectcontrol for an array of layers. How can I do that? – Catlover Mar 24 '14 at 21:04
1

Instead of removing the layer, why not remove all existing features using removeAllFeatures?

0

I think you shouldn't try to destroy the selectControl in the loop. If it is absolutely necessary, then try to destroy it after you removed the layers. Also I think you are trying to remove the name of the layer not the layer itself:

var mLayers = map.layers;
for(var a = 0; a < mLayers.length; a++ ){
if(mLayers[a].name == "Mylayer")
{
map.removeLayer(mLayers[a]); //instead of mLayers[a].name
map.layers[a].destroy();
}
};
map.removeControl(selectControl);
selectControl.destroy();
  • It gives another error: Uncaught TypeError: Cannot call method 'triggerEvent' of null – Catlover Mar 19 '14 at 17:33
  • and this error points at: OpenLayers.js: 684. Any other suggestion? – Catlover Mar 19 '14 at 17:34
  • 2
    after you remove the layer exit the for loop – Ralph Dell Mar 20 '14 at 14:40
  • @RalphDell: I tried it but gives the following errors: – Catlover Mar 21 '14 at 13:48
  • Uncaught TypeError: Cannot call method 'removeLayer' of null , at OpenLayers.js:827 – Catlover Mar 21 '14 at 13:49
0

I would not try to remove the layer, I would simply hide it. You can make it invisible in the map and in the layer switcher.

displayInLayerSwitcher

{Boolean} Display the layer’s name in the layer switcher. Default is true.

visibility

{Boolean} The layer should be displayed in the map. Default is true.

  • Making it invisible would not help. My case is to create a layer with some features in it. and later when user changes his prefered query, some other features need to be shown, so its the same layer but with different features. Therefore, I need to remove the layer and create it again with new features and then show it on the map. What is the best solution for doing this? – Catlover Mar 23 '14 at 18:28
  • I have updated the question. Do you have other suggestions? – Catlover Mar 24 '14 at 13:15
0

A few things seems to be problematic in your code.

  • You are not supposed to remove or destroy an array element when iterating over the array, you will mess up the indexes when iterating. Ralph Dell's comment is right if you can ensure that you have only one layer named 'Mylayer' that you want to remove.

  • You are no longer able to access the removed layer via map.layers[a] after you remove the layer from the map

  • The map.removeLayer function takes in layer object as parameter not its name

Some suggested code:

var mLayers = map.layers;
var remLayers = [];

for (var i=0; i<mLayer.length; i++) {
    if (mLayer[i].name == "Mylayer") {
        remLayers.push(mLayer[i]);
    }
}

for (var i=0; i<remLayers.length; i++) {
    remLayers[i].destroy();  // Note that the destroy function automatically take care to remove itself from the map it attached to
}

map.removeControl(selectControl);
selectControl.destroy();

Normally you just need to remove the layer from the map instead of destroy it, Javascript garbage will take care of it once the layer is not referenced any more. In that case, the second for loop can be changed into:

for (var i=0; i<remLayers.length; i++) {
    map.removeLayer(remLayers[i]);
}

The same applies for the selectControl, normally you just need to remove it from map.

  • Thank you for the tips. I tried your code, with the one with only removing layer and not destroying it. It did not give error, but also did not work (my layer was not removed from map!). Any other suggestions? – Catlover Mar 23 '14 at 18:25
  • Maybe you can update the original question with the new code so that we can check where's the problem. – mfdev Mar 24 '14 at 6:50
  • Thank you for your response. I have updated the question. Do you have other suggestions? – Catlover Mar 24 '14 at 13:16

Your Answer

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

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