OpenLayers WMS – Dynamic Filter on Tile (WMS) Layer

filteropenlayerswms

I have a tile layer with a WMS source coming from GeoServer. I want to add and change a filter to it when a user changes their selection. I can see some examples for OpenLayers 3 and Vector layers but the OpenLayers.Filter class has changed and I can't get it to have any effect.

import OlTileLayer from 'ol/layer/Tile';
import OlOr from 'ol/format/filter/Or';
import OlEq from 'ol/format/filter/EqualTo';



this.structureLayer = new OlTileLayer({
  source: new TileWMS({
    url: 'http://test.com/fpat/wms', 
    params: {'LAYERS': 'fpat:fpat_surveys',
              'TILED': true},
    serverType: 'geoserver',
    transition: 0
  })
});


 this.structureLayer.filter = new OlOr(new OlEq('structure_types', 'Natural') , new OlEq('structure_types', 'Other'));

When the user changes their selection I'll need to rebuild the filter and make sure the layer updates. The documentation for a vector layer with a spatial filter suggests this, but I I get an error because refresh doesn't exist

this.structureLayer.refresh({force: true})

Best Answer

You need to refresh the params of the source of structureLayer. Don't try to use OpenLayers 2 syntax thinking it would work by luck on OpenLayers 3+: OpenLayers 3+ is a full rewrite (remark comes from your attempt to use this.structureLayer.refresh({force: true}))

It should be more

// Get existing parameters collection
var params = this.structureLayer.getSource().getParams();
// I choose to use CQL_FILTER instead of sld
params.CQL_FILTER = "structure_types IN ('Natural', 'Other')";
// Uncomment line below and comment line above if you prefer using sld
// params.sld_body = "yourxmlfiltercontent"; 
this.structureLayer.getSource().updateParams(params);

You can use filter but you will need to create your own XML as the ol.format.filter are intended for WFS not WMS. That's why I've use cql_filter instead above (it does the same job with a more simple syntax)

You can see a demo to show "it works"

You should also consider using POST (default behaviour using GET and there are restrictions on length of HTTP GET call Url). You may need to look at this related post OpenLayers 3 WMS Styling Using SLD_BODY and POST request

PS: I'm using the "OpenLayers pre-ES6" syntax in the demo but the logic remains the same.