4

I've been trying to build my own WFS-T and followed the tutorial from https://medium.com/@goldrydigital/wfs-t-with-openlayers-3-16-6fb6a820ac58. I have copied the code as closely as possible. The code is supposed to draw a point, line, or polygon when I click on the button and save it to my PostGIS database. Here is the code:

<! DOCTYPE=html>
<html>
    <head>
        <link rel="stylesheet" href="https://openlayers.org/en/v4.6.4/css/ol.css" type="text/css">
        <! This is how he does his buttons >
        <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
        <style>
         .map {
          height: 100%;
          width: 100%;
         }
        </style>
        <script src="https://openlayers.org/en/v4.6.4/build/ol.js" type="text/javascript"></script>
        <script src="http://code.jquery.com/jquery-1.11.0.js"></script>
        <script src="https://code.getmdl.io/1.1.3/material.js"></script>
        <title>OpenLayers example</title>
    </head>
    <body>
        <div id="map" class="map"></div>
        <button id="btnPoint" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
        <i class="material-icons">add_location</i>
        </button>
        <button id="btnLine" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
        <i class="material-icons">timeline</i>
        </button>
        <button id="btnArea" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
        <i class="material-icons">signal_cellular_null</i>
        </button>
        <button id="btnEdit" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
        <i class="material-icons">build</i>
        </button>
        <button id="btnDelete" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
        <i class="material-icons">delete</i>
        </button>
        <! And now for the script!>

        <script type="text/javascript">
        var formatWFS = new ol.format.WFS();

        var formatGML = new ol.format.GML({
            featureNS: 'http://localhost:8080/geoserver/geolytix/',
            featureType: 'wfs_geom',
            srsName: 'EPSG:3857'
            });

        var xs = new XMLSerializer();

        var sourceWFS = new ol.source.Vector({
            loader: function (extent) {
            $.ajax('http://localhost:8080/geoserver/geolytix/ows?', {
            type: 'GET',
            data: {
                service: 'WFS',
                version: '1.1.0',
                request: 'GetFeature',
                typename: 'wfs_geom',
                srsname: 'EPSG:3857',
                bbox: extent.join(',') + ',EPSG:3857'
            }
            }).done(function (response) {
            sourceWFS.addFeatures(formatWFS.readFeatures(response));
            });
            },
            strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ()),
            strategy: ol.loadingstrategy.bbox,
            projection: 'EPSG:3857'
            });

        var layerWFS = new ol.layer.Vector({
        source: sourceWFS
        });

        var interaction;

        var interactionSelectPointerMove = new ol.interaction.Select({
            condition: ol.events.condition.pointerMove
            });

        var interactionSelect = new ol.interaction.Select({
            style: new ol.style.Style({
            stroke: new ol.style.Stroke({
            color: '#FF2828'
            })
            })
            });

        var interactionSnap = new ol.interaction.Snap({
            source: layerWFS.getSource()
            });

// The CartoDB map is working, but I think I'll use OSM as it looks better anyway.

        var map = new ol.Map({
        target: 'map',
        controls: [],
        interactions: [
        interactionSelectPointerMove,
        new ol.interaction.MouseWheelZoom(),
        new ol.interaction.DragPan()
        ],
        layers: [
        new ol.layer.Tile({
            source: new ol.source.OSM({
                url: 'https://cartodb-basemaps-{a-d}.global.ssl.fastly.net/dark_nolabels/{z}/{x}/{y}.png',
                opaque: false,
                attributions: []
            })
        }),
        layerWFS
        ],
        view: new ol.View({
        center: ol.proj.fromLonLat([-1.7, 53.2]),
        zoom: 6
        })
        });

// wfs-t <DON'T UNCOMMENT THIS LINE!>
        var dirty = {};
        var transactWFS = function (mode, f) {
        var node;
        switch (mode) {
        case 'insert':
            node = formatWFS.writeTransaction([f], null, null, formatGML);
            break;
        case 'update':
            node = formatWFS.writeTransaction(null, [f], null, formatGML);
            break;
        case 'delete':
            node = formatWFS.writeTransaction(null, null, [f], formatGML);
            break;
    }
    var payload = xs.serializeToString(node);
    $.ajax('http://localhost:8080/geoserver/geolytix/ows', {
        type: 'POST',
        dataType: 'xml',
        processData: false,
        contentType: 'text/xml',
        data: payload
    }).done(function() {
        sourceWFS.clear();
    });
    };

$('button').click(function () {
    $(this).siblings().removeClass('btn-active');
    $(this).addClass('btn-active');
    map.removeInteraction(interaction);
    interactionSelect.getFeatures().clear();
    map.removeInteraction(interactionSelect);

    switch ($(this).attr('id')) {

        case 'btnEdit':
            map.addInteraction(interactionSelect);
            interaction = new ol.interaction.Modify({
                features: interactionSelect.getFeatures()
            });
            map.addInteraction(interaction);
            map.addInteraction(interactionSnap);
            dirty = {};
            interactionSelect.getFeatures().on('add', function (e) {
                e.element.on('change', function (e) {
                    dirty[e.target.getId()] = true;
                });
            });
            interactionSelect.getFeatures().on('remove', function (e) {
                var f = e.element;
                if (dirty[f.getId()]) {
                    delete dirty[f.getId()];
                    var featureProperties = f.getProperties();
                    delete featureProperties.boundedBy;
                    var clone = new ol.Feature(featureProperties);
                    clone.setId(f.getId());
                    transactWFS('update', clone);
                }
            });
            break;

        case 'btnPoint':
            interaction = new ol.interaction.Draw({
                type: 'Point',
                source: layerWFS.getSource()
            });
            map.addInteraction(interaction);
            interaction.on('drawend', function (e) {
                transactWFS('insert', e.feature);
            });
            break;

        case 'btnLine':
            interaction = new ol.interaction.Draw({
                type: 'LineString',
                source: layerWFS.getSource()
            });
            map.addInteraction(interaction);
            interaction.on('drawend', function (e) {
                transactWFS('insert', e.feature);
            });
            break;

        case 'btnArea':
            interaction = new ol.interaction.Draw({
                type: 'Polygon',
                source: layerWFS.getSource()
            });
            interaction.on('drawend', function (e) {
                transactWFS('insert', e.feature);
            });
            map.addInteraction(interaction);
            break;

        case 'btnDelete':
            interaction = new ol.interaction.Select();
            interaction.getFeatures().on('add', function (e) {
                transactWFS('delete', e.target.item(0));
                interactionSelectPointerMove.getFeatures().clear();
                interaction.getFeatures().clear();
            });
            map.addInteraction(interaction);
            break;

        default:
            break;
    }
});
</script>
</body>
</html>

I have some outdated comments (like the one about OSM)- just ignore those.

I have checked the log and I am getting this error: ERROR [geoserver.ows] - org.geoserver.wfs.WFSException: No such feature type http://localhost:8080/geoserver/geolytix/:wfs_geom.

4
  • what is not working? what request is sent to GeoServer? what response is returned? what error messages do you see in the log file?
    – Ian Turton
    Commented Mar 19, 2018 at 8:41
  • Sorry, I should've been less vague. It's the draw tool that's not working. I know that when I click the point, line, or polygon button it is supposed to draw it on the map and save it to my PostGIS database. Right now it acts like it's going to draw, but clicking on the map does nothing when I'm drawing a point and it only briefly draws a line or polygon that disappears when I finish. I'm not a programmer by any means, just savvy enough to understand the code. How do I tell what is being sent to Geoserver or what response is being returned? I could try to find the log file later. Commented Mar 19, 2018 at 16:13
  • Okay, the error message has been added to my question! Commented Mar 19, 2018 at 21:23
  • can u please elaborate the way you published your layer in geoserver. I am still confused with the bbox and wfst service Commented Apr 10, 2019 at 17:10

1 Answer 1

3

Yay, I solved the problem: I just needed to shorten the namespace at var formatGML = new ol.format.GML({ featureNS: 'http://localhost:8080/geoserver/geolytix', featureType: 'wfs_geom', srsName: 'EPSG:3857' });

to just

var formatGML = new ol.format.GML({
        featureNS: 'geolytix',
        featureType: 'wfs_geom',
        srsName: 'EPSG:3857'
        });

and it works great!

1
  • It problem is solved. Mark it as accepted answer.
    – neogeomat
    Commented Mar 20, 2018 at 3:15

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.