6

I am having a problem with the styling of a WFS vector layer from GeoServer after cloning features from it and adding them to a new feature.

First I create a new empty vector layer and add it to the map object:

var polyAdHoc = new OpenLayers.Layer.Vector("Search Results");
map.addLayer(polyAdHoc);

Then I use a selectFeature control to get a feature from another WFS layer:

var mLayer = map.getLayersBy('name', 'Test Stands 4thQ 2012' );
var name = mLayer[0].name;
var layerFeatureArray = mLayer[0].features; 
ctrlSearch.select(layerFeatureArray[x]);

Then I clone the feature from the WFS vector layer:

var cloneFeature = layerFeatureArray[x].clone();

Then I add the cloned feature to the vector layer :

polyAdHoc.addFeatures(cloneFeature); 

Then I set the style of the feature in the new vector layer so that it will appear hilighted against the original layer:

cloneFeature.style.strokeColor = '#FF0000';
cloneFeature.style.strokeWidth = 3;
cloneFeature.style.fillOpacity = 0.2;
cloneFeature.style.fillColor = '#FF0000';

The new layer refreshes and the map looks fine until I turn the original WFS layer off and then on again. When it comes on again the features from the WFS that were cloned now share the same style as the cloned features and I want them to stay the same as they were originally.

I do not want the style to apply to the original WFS shape, only the features in the new layer.

Even more frustrating, if I try to reset the original WFS feature style it changes the new vector layers style so I end up with the same problem of both layers having the same style again.

I am using OpenLayers 2.12 and GeoServer 2.1.4.

Any suggestions would be appreciated. Thanks!


@CaptDragon - EDIT:


Here is the complete code I am using now. Everything here works great except for the fact that this changes the style of the features in the original WFS layer.

I have modified this slightly from my original post. Instead of cloning the features I am just doing a straight-up addFeature to the new vector layer.

//FIRST I GET THE WFS LAYER I WANT TO COPY FEATURES FROM
var mLayer = map.getLayersBy('name', 'Test Stands 4thQ 2012' );
/THEN I CREATE A VARIABLE FOR THE ARRAY OF FEATURES IN THE LAYER
var layerFeatureArray = mLayer[0].features; //the array of features in a layer
//THEN I CREATE THE NEW EMPTY VECTOR LAYER
var polyAdHoc = new OpenLayers.Layer.Vector("Search Results");
//I ADD THE NEW EMPTY VECTOR LAYER TO THE MAP OBJECT
map.addLayer(polyAdHoc);


//THE selectItems IS AN ARRAY OF VALUES I RETRIEVE FROM A DATABASE
//I LOOP THROUGH THESE ITEMS 
for (a = 0; a < selectItems.length; a++) {
//THEN I LOOP THROUGH THE FEATURES IN THE WFS LAYER 
    for (x = 0; x < layerFeatureArray.length; x++) {
//IF THE UID FROM THE WFS FEATURE MATCHES THE VALUE FROM THE selectItems VAR 
        if (layerFeatureArray[x].attributes['UID'] == selectItems[a]) {                
            //I ASSIGN A VARIABLE TO THE FEATURE
            var searchFeature = layerFeatureArray[x];
            //AND THEN ADD THE FEATURE TO MY NEW VECTOR LAYER 
            polyAdHoc.addFeatures(searchFeature);
            //AS I ADD EACH FEATURE I GIVE IT STYLING
            searchFeature.style.strokeColor = '#FF0000';
            searchFeature.style.strokeWidth = 3;
            searchFeature.style.fillColor = '#FF0000';
            searchFeature.style.fillOpacity = 0.2;
            break;
        }//END if 
    } //END feature array FOR LOOP  
} //END selectItems FOR 

//ZOOM TO THE EXTENT OF THE NEW VECTOR LAYER
map.zoomToExtent(polyAdHoc.getDataExtent()); 
5
  • Sounds like a bug, but can you try cloning the style also?
    – CaptDragon
    Commented Jan 10, 2013 at 14:33
  • 1
    I have tried it but cannot seem to get the syntax correct. I tried: var cloneStyle = layerFeatureArray[x].style.clone(); but it returns "undefined" Thanks Commented Jan 10, 2013 at 14:39
  • You could also have a closure in your code, but without more code within context, I can't be sure.
    – CaptDragon
    Commented Jan 10, 2013 at 18:10
  • @CaptDragon - Thank you for taking the time to look at my issue. I have added the complete code above. Commented Jan 10, 2013 at 18:47
  • I have noticed that cloned features share the same featureID as the original. Is it possible that the cloned featureID's are still assigned to the original layer and are using the style from that layer? Commented Jan 10, 2013 at 19:47

3 Answers 3

2

I attacked the problem from a different direction. Instead of trying to make it work using clone() or addFeatures I ended up using the WKT method. It probably isn't the best solution to the problem but it works. Here is the code I am using now:

function createSelectedFeatureLayer(selectItems) { 
//GET THE NAME OF THE LAYER TO SELECT FROM
var mLayer = map.getLayersBy('name', 'Test Stands 4thQ 2012' );
//SET A VARIABLE TO THE LAYERS FEATURE ARRAY
var layerFeatureArray = mLayer[0].features; 
//SET UP A STYLE MAP FOR THE FEATURES WE ARE GOING TO CREATE
var vctrStyleMap = new OpenLayers.StyleMap({
    fillColor: '#FF0000', 
    fillOpacity: 0.5,
    strokeColor: '#FF0000',
    strokeWidth: 2.5
});

//CREATE A NEW VARIABLE TO HOLD A WELL KNOWN TEXT OBJECT
wkt = new OpenLayers.Format.WKT();
//CREATE A NEW EMPTY VECTOR LAYER TO HOLD THE FEATURES WE WILL CREATE - ASSIGN THE STYLEMAP VARIABLE TO IT
vectors = new OpenLayers.Layer.Vector("Search Results", { styleMap: vctrStyleMap });
//ADD THE NEW EMPTY VECTOR LAYER TO THE MAP OBJECT
map.addLayer(vectors);

//selectItems IS AN ARRAY OF VALUES I AM MATCHING AGAINST - LOOP THROUGH THIS LIST
for (a = 0; a < selectItems.length; a++) {
//LOOP THROUGH THE FEATURES ARRAY FROM THE LAYER WE ARE SELECTING FROM
    for (x = 0; x < layerFeatureArray.length; x++) {
//IF THE UID OF THE FEATURE FROM THE SELECTION LAYER MATCHES THE VALUE FROM THE INPUT ARRAY
        if (layerFeatureArray[x].attributes['UID'] == selectItems[a]) {                
            //SET A VARIABLE TO THE FEATURE
            var searchFeature = layerFeatureArray[x];
            //SET A VARIABLE TO THE WELL KNOWN TEXT VALUE OF THE FEATURE OBJECT - WRITE IT!
            var str = wkt.write(searchFeature);
            //READ THE WELL KNOWN TEXT STRING AND ASSIGN IT TO THE features VARIABLE
            var features = wkt.read(str);
            //ADD THE FEATURE TO THE VECTOR LAYER WE CREATED EARLIER
            vectors.addFeatures(features);

            break;
        }//END if 
    } //END feature array FOR LOOP  
} //END selItems array FOR LOOP

vectors.redraw();//REDRAW THE LAYER
map.zoomToExtent(vectors.getDataExtent()); //ZOOM TO THE NEW LAYERS 
map.setLayerZIndex(vectors, 100); //PUT THE SELECTION LAYER ON TOP

}
1

Have a look at OpenLayers Styling. The best way to do this I think would be to use attribute replacement syntax when defining your vector layers. This allows your styles to be rendered and changed by attributes on a per-feature basis. So in your example, I might do something like this:

var styleMap = new OpenLayers.StyleMap({
    fillColor: '${fillColor}', // use attribute replacement syntax
    fillWidth: '${fillWidth}',
    strokeColor: '${strokeColor}',
    strokeWidth: '${strokeWidth}'
});
var mLayer = map.getLayersBy('name', 'Test Stands 4thQ 2012' );
var layerFeatureArray = mLayer[0].features;
var polyAdHoc = new OpenLayers.Layer.Vector("Search Results", { styleMap: styleMap });
map.addLayer(polyAdHoc);


for (a = 0; a < selectItems.length; a++) {
    for (x = 0; x < layerFeatureArray.length; x++) {
        if (layerFeatureArray[x].attributes['UID'] == selectItems[a]) {                
            var searchFeature = layerFeatureArray[x].clone();
            searchFeature.attributes.strokeColor = '#FF0000';
            searchFeature.attributes.strokeWidth = 3;
            searchFeature.attributes.fillColor = '#FF0000';
            searchFeature.attributes.fillOpacity = 0.2;
            polyAdHoc.addFeatures(searchFeature);
            break;
        }
    }
}
polyAdHoc.redraw(); // don't forget to refresh the layer
map.zoomToExtent(polyAdHoc.getDataExtent());
1
  • Thanks Kyle. That was a great suggestion and partially solved the problem. After adding your script this is the behavior now: 1) After the new vector loads it is styled correctly. 2) When I turn off the new vector the original WFS layer is styled correctly. 3) When I turn the original WFS layer off and then on it shows all the stands that were copied to the new vector with the new vectors style. 4) Then if I turn the new vector on and off the original WFS is styled correctly again. Commented Jan 10, 2013 at 20:44
0

A couple of suggestions:

In your case I would style features and then add them to the map. In that order. Or else you'll need to call layer.redraw(); redraw doc. / example

Also, I don't know if your WFS layer returns features with individual styles. It probably has a stylemap for the entire layer. But feature.style by default is null. So you'll need to instantiate a style object before you can assign style properties to it.

So try something like this:

var searchFeature = layerFeatureArray[0];
//AS I ADD EACH FEATURE I GIVE IT STYLING

searchFeature.style = new OpenLayers.Style(); //<-- call constructor.
searchFeature.style.strokeColor = '#FF0000';
searchFeature.style.strokeWidth = 3;
searchFeature.style.fillColor = '#FF0000';
searchFeature.style.fillOpacity = 0.2;
//AND THEN ADD THE FEATURE TO MY NEW VECTOR LAYER 
polyAdHoc.addFeatures(searchFeature);
3
  • Thanks again CaptDragon, unfortunately this results in the same behavior as when I started. The style applied to the new vector layer features carries over to the original WFS layer. Some how the copied (or cloned) features are connected and keep picking up each others styling. I have tried assigning new featureID's to the vector features but I cannot break the pointer that keeps looking at the WFS layer. Commented Jan 10, 2013 at 22:08
  • @ToddKrueger: Si the JavaScript page this code is in, is it sensitive? Can you pastebin.com it?
    – CaptDragon
    Commented Jan 11, 2013 at 0:20
  • CaptDragon - I was able to solve the problem using a different approach. Thank you for your comments and assistance! Commented Jan 11, 2013 at 20:53

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.