1

I'm adding some layers on a base map using OpenLayers 2. 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.

2

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();

}
1

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();
1

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.

1

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.

1

Instead of removing the layer, try removing all existing features using removeAllFeatures.

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.