Skip to content

Commit d8e0649

Browse files
authored
Merge pull request #427 from sronveaux/wfs-featuresloadend-featuresloaderror-events
Fix featuresloadend and featuresloaderror events not fired properly by WFS layers
2 parents d7b707b + b96c20d commit d8e0649

File tree

3 files changed

+125
-11
lines changed

3 files changed

+125
-11
lines changed

app-starter/static/app-conf-projected.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
{
7979
"type": "WFS",
8080
"lid": "dutch-nat-parks",
81-
"url": "https://service.pdok.nl/rvo/nationaleparken/wfs/v2_0?",
81+
"url": "https://service.pdok.nl/rvo/nationaleparken/wfs/v2_0",
8282
"typeName": "nationaleparken:nationaleparken",
8383
"version": "2.0.0",
8484
"maxFeatures": 10,

src/factory/Layer.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -225,42 +225,48 @@ export const LayerFactory = {
225225

226226
const vectorSource = new VectorSource({
227227
format: new this.formatMapping[lConf.format](lConf.formatConfig),
228-
loader: (extent) => {
228+
loader: (extent, resolution, projection, success, failure) => {
229229
// assemble WFS GetFeature request
230-
const pre = lConf.url.includes('?') ? '&' : '?';
231-
let wfsRequest = lConf.url + pre + 'service=WFS&' +
232-
'version=' + lConf.version + '&request=GetFeature&' +
233-
'typename=' + lConf.typeName + '&' +
234-
'outputFormat=' + outputFormat + '&srsname=' + lConf.projection;
230+
const params = {
231+
service: 'WFS',
232+
version: lConf.version,
233+
request: 'GetFeature',
234+
typename: lConf.typeName,
235+
outputFormat,
236+
srsname: lConf.projection
237+
};
235238

236239
// add WFS version dependent feature limitation
237240
if (Number.isInteger(parseInt(lConf.maxFeatures))) {
238241
if (lConf.version.startsWith('1.')) {
239-
wfsRequest += '&maxFeatures=' + lConf.maxFeatures;
242+
params.maxFeatures = lConf.maxFeatures;
240243
} else {
241-
wfsRequest += '&count=' + lConf.maxFeatures;
244+
params.count = lConf.maxFeatures;
242245
}
243246
}
244247
// add bbox filter
245248
if (lConf.loadOnlyVisible !== false) {
246249
if (mapSrs !== lConf.projection) {
247250
extent = applyTransform(extent, getTransform(mapSrs, lConf.projection));
248251
}
249-
wfsRequest += '&bbox=' + extent.join(',') + ',' + lConf.projection + '';
252+
params.bbox = extent.join(',') + ',' + lConf.projection;
250253
}
251254

252255
// load data from WFS, parse and add to vector source
253256
const request = {
254257
method: 'GET',
255-
url: wfsRequest
258+
url: lConf.url,
259+
params
256260
};
257261
axios(request)
258262
.then(response => {
259263
const feats = vectorSource.getFormat().readFeatures(response.data);
260264
vectorSource.addFeatures(feats);
265+
success(feats);
261266
})
262267
.catch(() => {
263268
vectorSource.removeLoadedExtent(extent);
269+
failure();
264270
});
265271
},
266272
strategy: lConf.loadOnlyVisible !== false ? bboxStrategy : undefined

tests/unit/specs/factory/Layer.spec.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import KmlFormat from 'ol/format/KML';
1515
import Map from 'ol/Map';
1616
import View from 'ol/View';
1717

18+
import axios from 'axios';
19+
import MockAdapter from 'axios-mock-adapter';
20+
1821
describe('LayerFactory', () => {
1922
it('is defined', () => {
2023
expect(LayerFactory).to.not.be.an('undefined');
@@ -193,4 +196,109 @@ describe('LayerFactory', () => {
193196
expect(layer.getSource() instanceof VectorTileSource);
194197
});
195198
});
199+
200+
describe('WFS layer', () => {
201+
describe('Events', () => {
202+
let divElement;
203+
let wfsLayer;
204+
let axiosMock;
205+
const layerURL = 'https://a-wfs-url.de';
206+
const fetchResults = JSON.stringify({
207+
type: 'FeatureCollection',
208+
features: [
209+
{
210+
type: 'Feature',
211+
id: '1',
212+
geometry: {
213+
type: 'Polygon',
214+
coordinates: [[4.0, 51.0], [4.5, 50.5], [5.0, 51.0], [4.0, 51.0]]
215+
}
216+
}
217+
]
218+
});
219+
220+
function createMapTargetElement () {
221+
const targetElement = document.createElement('div');
222+
targetElement.style.cssText = 'width:640px; height:480px';
223+
return targetElement;
224+
};
225+
226+
function applyAxiosMock (error = false) {
227+
axiosMock = new MockAdapter(axios);
228+
if (!error) {
229+
axiosMock.onGet(layerURL).reply(200, fetchResults);
230+
} else {
231+
axiosMock.onGet(layerURL).networkError();
232+
}
233+
};
234+
235+
beforeEach(() => {
236+
const layerConf = {
237+
type: 'WFS',
238+
lid: 'a-wfs',
239+
url: layerURL,
240+
typeName: 'foo:tn',
241+
version: '2.0.0',
242+
format: 'GeoJSON',
243+
projection: 'EPSG:3857',
244+
visible: false
245+
};
246+
247+
divElement = createMapTargetElement();
248+
document.body.append(divElement);
249+
250+
const olMap = new Map({
251+
view: new View({
252+
center: [0, 0],
253+
zoom: 1
254+
}),
255+
layers: [],
256+
target: divElement
257+
});
258+
wfsLayer = LayerFactory.createWfsLayer(layerConf, olMap);
259+
olMap.addLayer(wfsLayer);
260+
});
261+
262+
it('fires the featuresloadstart event when displayed', done => {
263+
applyAxiosMock();
264+
265+
wfsLayer.getSource().on('featuresloadstart', () => {
266+
done();
267+
})
268+
269+
wfsLayer.setVisible(true);
270+
});
271+
272+
it('fires the featuresloadend event when features retrieved', done => {
273+
applyAxiosMock();
274+
275+
wfsLayer.getSource().on('featuresloadend', () => {
276+
done();
277+
})
278+
279+
wfsLayer.setVisible(true);
280+
});
281+
282+
it('fires the featuresloaderror event when error during features retrieval', done => {
283+
applyAxiosMock(true);
284+
285+
wfsLayer.getSource().on('featuresloaderror', () => {
286+
done();
287+
})
288+
289+
wfsLayer.setVisible(true);
290+
});
291+
292+
afterEach(() => {
293+
if (axiosMock) {
294+
axiosMock.restore();
295+
}
296+
297+
if (divElement) {
298+
divElement.remove();
299+
divElement = undefined;
300+
}
301+
});
302+
});
303+
});
196304
});

0 commit comments

Comments
 (0)