Skip to content

Tiny WFS-T client to insert, modify and delete features on GeoServers using OpenLayers.

License

Notifications You must be signed in to change notification settings

GastonZalba/ol-wfst

Repository files navigation

OpenLayers WFST

npm version npm license

Tiny WFS-T client to insert (drawing/uploading), modify and delete features on GeoServers using OpenLayers. Layers with these types of geometries are supported: GeometryCollection (in this case, you can choose the geometry type of each element to draw), Point, MultiPoint, LineString, MultiLineString, Polygon and MultiPolygon.

Tested with OpenLayers version 5, 6, 7, 8 and 9.

Drawing

Editing fields

Usage

See Wfst Options for more details.

import Wfst, { Geoserver, WmsLayer, WfsLayer } from 'ol-wfst';
import { Fill, Stroke, Circle, Style } from 'ol/style';

// Style
import 'ol-wfst/lib/scss/ol-wfst.css';
import 'ol-wfst/lib/scss/ol-wfst.bootstrap5.css'; // Do not import if you already have boostrap css

// Optional credentials
const password = 123456;
const username = 'username';

const geoserver = {
    url: 'https://mysite.com/geoserver/myworkspace/ows',
    advanced: {
        getCapabilitiesVersion: '2.0.0',
        getFeatureVersion: '1.0.0',
        describeFeatureTypeVersion: '1.1.0',
        lockFeatureVersion: '1.1.0',
        projection: 'EPSG:3857'
    },
    // Maybe you wanna add this on a proxy, at the backend
    headers: { Authorization: 'Basic ' + btoa(username + ':' + password) }
};

const wfsLayer = new WfsLayer({
    name: 'myPointsLayer', // Name of the layer on the GeoServer
    label: 'Photos', // Optional Label to be displayed in the controller
    geoserver: geoserver,
    zIndex: 99,

    // WfsLayers need a custom style
    style: new Style({
        image: new Circle({
            radius: 7,
            fill: new Fill({
                color: '#000000'
            }),
            stroke: new Stroke({
                color: [255, 0, 0],
                width: 2
            })
        })
    }),

    // See [geoserverVendor](#geoservervendor) for more details.
    geoserverVendor: {
        cql_filter: 'id > 50',
        maxFeatures: 500
    },

    beforeTransactFeature: function (feature, transactionType) {
        if (transactionType === 'insert') {
            // Maybe add a custom value o perform an action before insert features
            feature.set('customProperty', 'customValue', true);
        } else if (transactionType === 'update') {
            // ... //
        } else if (transactionType === 'delete') {
            // .. //
        }

        return feature;
    }
});

const wmsLayer = new WmsLayer({
    name: 'myMultiGeometryLayer',
    label: 'Other elements',
    geoserver: geoserver,
    // See [geoserverVendor](#geoservervendor) for more details.
    geoserverVendor: {
        cql_filter: 'id > 50',
        buffer: 50,
        maxFeatures: 500
    },
    beforeTransactFeature: function (feature, transactionType) {
        if (transactionType === 'insert') {
            // Maybe add a custom value o perform an action before insert features
            feature.set('customProperty', 'customValue', true);
        } else if (transactionType === 'update') {
            // ... //
        } else if (transactionType === 'delete') {
            // .. //
        }

        return feature;
    },
    beforeShowFieldsModal: function (field, value, formElement) {
        // Transform default input to a custom select
        if (field.name === 'source') {
            const createSelect = (name, options) => {
                const createOption = (opt) => {
                    const option = document.createElement('option');
                    option.value = opt.value;
                    option.label = opt.label;

                    if (opt.value === value) {
                        option.selected = true;
                    }
                    return option;
                };

                const select = document.createElement('select');
                select.className = 'ol-wfst--input-field-input';
                select.name = name;

                options.forEach((opt) => {
                    select.appendChild(createOption(opt));
                });

                return select;
            };

            return createSelect('source', [
                { label: 'Select source', value: '' },
                { label: 'Option 1', value: 'option1' },
                { label: 'Option 2', value: 'option2' }
            ]);
        } else if (field.name === 'registroid') {
            // add default class to the HTMLElement in a particular field
            formElement.classList.add('custom-field-class');
        }

        return formElement;
    }
});

const wfst = new Wfst({
    layers: [wfsLayer, wmsLayer],
    language: 'en',
    showUpload: true
});

map.addControl(wfst);

Useful methods

See [#wfsSource]

wmsLayer.setCustomParam('cql_filter', `id = 28`);
wmsLayer.setCustomParam('env', `tags=true`);

Adding features programatically

const feature = new ol.Feature({
    geometry: new ol.geom.MultiPoint([[`-57.1145}`, `-36.2855`]])
});
const inserted = await myWmsLayer.insertFeatures([feature]);

if (inserted) {
    alert('Feature inserted');
} else {
    alert('Feature not inserted');
}

Events

wfst instance events

wfst.on(
    ['modifystart', 'modifyend', 'drawstart', 'drawend', 'load', 'visible'],
    function (evt) {
        console.log(evt);
    }
);

wfst.on(['describeFeatureType'], function (evt) {
    console.log(evt.layer, evt.data);
});

Geoserver events

geoserver.on(['getCapabilities'], function (evt) {
    console.log(evt.data);
});

Layers events

WMS Layer

wmsLayer.on(['change:describeFeatureType'], function (evt) {
    console.log(evt);
});

Source TileWMS Events

wmsLayer.getSource().on([...])

WFS Layer

wfsLayer.on(['change:describeFeatureType'], function (evt) {
    console.log(evt);
});

VectorSource Events

wfsLayer.getSource().on([...])

Some considerations

  • If the features/vertex appear to be slightly offset after adding them, check the Number of Decimals in your Workplace, you may have to increment that to have a more accurete preview.
  • You can configure a Basic Authentication or an HTTP Header Proxy Authentication with this client, but in some cases is recommended setting that on an reverse proxy on the backend.
  • If you don't use a reverse proxy, remeber configure cors

Changelog

See CHANGELOG for details of changes in each release.

Install

Browser

JS

Load ol-wfst.js after OpenLayers. The available classes are Wfst, Wfst.Geoserver, Wfst.WfsLayer and Wfst.WmsLayer.

<script src="https://unpkg.com/ol-wfst@4.4.0"></script>

CSS

<link rel="stylesheet" href="https://unpkg.com/ol-wfst@4.4.0/dist/css/ol-wfst.min.css" />
<link rel="stylesheet" href="https://unpkg.com/ol-wfst@4.4.0/dist/css/ol-wfst.bootstrap5.min.css" />

Parcel, Webpack, etc.

NPM package: ol-wfst.

Install the package via npm

npm install ol-wfst

JS

import Wfst, { Geoserver, WmsLayer, WfsLayer } from 'ol-wfst';

CSS

// scss
import 'ol-wfst/lib/style/scss/ol-wfst.scss';
import 'ol-wfst/lib/style/scss/-ol-wfst.bootstrap5.scss';

// or css
import 'ol-wfst/lib/style/css/ol-wfst.css';
import 'ol-wfst/lib/style/css/ol-wfst.bootstrap5.css';

TypeScript type definition

TypeScript types are shipped with the project in the dist directory and should be automatically used in a TypeScript project. Interfaces are provided for Wfst Options.

API

Table of Contents

BaseGeoserverVendor

key

Add any other param

cql_filter

https://docs.geoserver.org/latest/en/user/services/wms/vendor.html#cql-filter

Type: string

sortBy

https://docs.geoserver.org/latest/en/user/services/wms/vendor.html#sortBy

Type: string

featureid

https://docs.geoserver.org/latest/en/user/services/wms/vendor.html#featureid

Type: string

filter

https://docs.geoserver.org/latest/en/user/services/wms/vendor.html#filter

Type: string

format_options

WMS: https://docs.geoserver.org/latest/en/user/services/wms/vendor.html#format-options WFS: https://docs.geoserver.org/latest/en/user/services/wfs/vendor.html#format-options

Type: string

maxFeatures

https://docs.geoserver.org/latest/en/user/services/wms/vendor.html#maxfeatures-and-startindex

Type: (string | number)

startIndex

https://docs.geoserver.org/latest/en/user/services/wms/vendor.html#maxfeatures-and-startindex

Type: (string | number)

propertyname

https://docs.geoserver.org/latest/en/user/services/wms/vendor.html#propertyname

Type: string

Wfst

Extends ol/control/Control~Control

Tiny WFS-T client to insert (drawing/uploading), modify and delete features on GeoServers using OpenLayers. Layers with these types of geometries are supported: "GeometryCollection" (in this case, you can choose the geometry type of each element to draw), "Point", "MultiPoint", "LineString", "MultiLineString", "Polygon" and "MultiPolygon".

Parameters

getLayers

Get all the layers in the ol-wfst instance

Returns Array<(WfsLayer | WmsLayer)>

getLayerByName

Get a layer

Parameters
  • layerName (optional, default '')

Returns (WfsLayer | WmsLayer)

activateDrawMode

Activate/deactivate the draw mode

Parameters

Returns void

activateEditMode

Activate/desactivate the edit mode

Parameters
  • bool (optional, default true)

Returns void

Geoserver

Extends ol/Object~BaseObject

Parameters

getCapabilities

Returns XMLDocument

getParsedCapabilities

Only work for 2.0.0 getCapabilities version

Returns any

setUrl

Parameters
  • url string
  • opt_silent (optional, default false)

Returns void

getUrl

Returns string

setHeaders

Parameters
  • headers HeadersInit (optional, default {})
  • opt_silent (optional, default false)

Returns void

getHeaders

Returns HeadersInit

setCredentials

Parameters
  • credentials RequestCredentials (optional, default null)
  • opt_silent (optional, default false)

Returns void

getCredentials

Returns RequestCredentials

setAdvanced

Parameters
  • advanced GeoServerAdvanced (optional, default {})
  • opt_silent (optional, default false)

Returns void

getAdvanced

Returns GeoServerAdvanced

hasTransaction

Returns boolean

hasLockFeature

Returns boolean

getUseLockFeature

Returns boolean

setUseLockFeature

Parameters
  • useLockFeature boolean
  • opt_silent (optional, default false)

Returns void

isLoaded

Returns boolean

getState

getAndUpdateCapabilities

Get the capabilities from the GeoServer and check all the available operations.

Returns Promise<XMLDocument>

_removeFeatures

Parameters
  • features Array<Feature<Geometry>>

lockFeature

Lock a feature in the geoserver. Useful before editing a geometry, to avoid changes from multiples suers

Parameters

Returns Promise<string>

WfsLayer

Extends ol/layer/Vector~VectorLayer

Layer to retrieve WFS features from geoservers https://docs.geoserver.org/stable/en/user/services/wfs/reference.html

Parameters

refresh

setCustomParam

Use this to update Geoserver Wms Vendors (https://docs.geoserver.org/latest/en/user/services/wms/vendor.html) and other arguements (https://docs.geoserver.org/stable/en/user/services/wms/reference.html#getmap) in all the getMap requests.

Example: you can use this to change the style of the WMS, add a custom sld, set a cql_filter, etc.

Parameters
  • paramName string
  • value string Use undefined or null to remove the param (optional, default null)
  • refresh (optional, default true)

Returns URLSearchParams

WmsLayer

Extends ol/layer/Tile~TileLayer

Layer to retrieve WMS information from geoservers https://docs.geoserver.org/stable/en/user/services/wms/reference.html

Parameters

refresh

setCustomParam

Use this to update Geoserver Wfs Vendors (https://docs.geoserver.org/latest/en/user/services/wfs/vendor.html) and other arguements (https://docs.geoserver.org/stable/en/user/services/wfs/reference.html) in all the getFeature requests.

Example: you can use this to set a cql_filter, limit the numbers of features, etc.

Parameters
  • paramName string
  • value string (optional, default null)
  • refresh (optional, default true)

Returns URLSearchParams

Options

[interface] - Wfst Options specified when creating a Wfst instance

Default values:

{
 layers: null,
 evtType: 'singleclick',
 active: true,
 showControl: true,
 language: 'en',
 i18n: {...}, // according to language selection
 uploadFormats: '.geojson,.json,.kml',
 processUpload: null,
}

processUpload

Triggered to allow implement custom functions or to parse other formats than default by filtering the extension. If this doesn't return features, the default function will be used to extract them.

Parameters
  • file File

Returns Array<Feature<Geometry>>

layers

Layers to be loaded from the geoserver

Type: Array<(WfsLayer | WmsLayer)>

active

Init active

Type: boolean

evtType

The click event to allow selection of Features to be edited

Type: ("singleclick" | "dblclick")

showControl

Show/hide the control map

Type: boolean

modal

Modal configuration

Type: {animateClass: string?, animateInClass: string?, transition: number?, backdropTransition: number?, templates: {dialog: (string | HTMLElement)?, headerClose: (string | HTMLElement)?}?}

language

Language to be used

Type: ("es" | "en" | "zh")

i18n

Custom translations

Type: I18n

showUpload

Show/hide the upload button

Type: boolean

uploadFormats

Accepted extension formats on upload Example: ".json,.geojson"

Type: string

LayerOptions

Extends Omit<VectorLayerOptions<any>, 'source'>

[interface] - Parameters to create the layers and connect to the GeoServer

You can use all the parameters supported by OpenLayers

Default values:

{
 name: null,
 geoserver: null,
 label: null, // `name` if not provided
 strategy: all,
 geoserverVendor: null
}

beforeTransactFeature

Triggered before inserting new features to the Geoserver. Use this to insert custom properties, modify the feature, etc.

Parameters
  • feature Feature<Geometry>
  • transaction TransactionType

Returns Feature<Geometry>

name

Layer name in the GeoServer

Type: string

geoserver

Geoserver Object

Type: Geoserver

label

Label to be displayed in the widget control

Type: string

geoserverVendor

Available geoserver options

Type: (WfsGeoserverVendor | WmsGeoserverVendor)

strategy

Strategy function for loading features. Only for WFS By default all strategy is used

Type: LoadingStrategy

beforeShowFieldsModal

Hook to customize the html elements showed in the fields modal Return null to hide the field from the modal

Type: function (field: IProperty, value: string, formElement: HTMLElement): (HTMLElement | string | null)

GeoserverOptions

[interface]

url

Url for OWS services. This endpoint will recive the WFS, WFST and WMS requests

Type: string

advanced

Advanced options for geoserver requests

Type: GeoServerAdvanced

headers

Http headers for GeoServer requests https://developer.mozilla.org/en-US/docs/Web/API/Request/headers

Type: HeadersInit

credentials

Credentials for fetch requests https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials

Default is 'same-origin'

Type: RequestCredentials

useLockFeature

Use LockFeatue request on GeoServer when selecting features. Prevents a feature from being edited through a persistent feature lock. This is not always supportedd by the GeoServer. See https://docs.geoserver.org/stable/en/user/services/wfs/reference.html

Type: boolean

GeoServerAdvanced

[interface]

  • Default values:
{
  getCapabilitiesVersion: '2.0.0',
  getFeatureVersion: '1.0.0',
  describeFeatureTypeVersion: '1.1.0',
  lockFeatureVersion: '1.1.0',
  wfsTransactionVersion: '1.1.0',
  projection: 'EPSG:3857',
  lockFeatureParams: {
    expiry: 5,
    lockId: 'Geoserver',
    releaseAction: 'SOME'
  }
}

WfsGeoserverVendor

Extends BaseGeoserverVendor

[interface] - WFS geoserver options https://docs.geoserver.org/latest/en/user/services/wfs/vendor.html

strict

https://docs.geoserver.org/latest/en/user/services/wfs/vendor.html#xml-request-validation

Type: boolean

WmsGeoserverVendor

Extends BaseGeoserverVendor

[interface] - WMS geoserver options https://docs.geoserver.org/latest/en/user/services/wms/vendor.html

buffer

https://docs.geoserver.org/latest/en/user/services/wms/vendor.html#buffer

Type: (string | number)

env

https://docs.geoserver.org/latest/en/user/services/wms/vendor.html#env

Type: string

clip

https://docs.geoserver.org/latest/en/user/services/wms/vendor.html#clip

Type: string

styles

Styles in which layers are to be rendered. Value is a comma-separated list of style names, or empty if default styling is required. Style names may be empty in the list, to use default layer styling.

Type: string

transparent

Whether the map background should be transparent. Values are true or false. Default is false

Type: boolean

bgcolor

Background color for the map image. Value is in the form RRGGBB. Default is FFFFFF (white).

Type: string

time

Time value or range for map data. See Time Support in GeoServer WMS for more information.

Type: string

sld

A URL referencing a StyledLayerDescriptor XML file which controls or enhances map layers and styling

Type: string

sld_body

A URL-encoded StyledLayerDescriptor XML document which controls or enhances map layers and styling

Type: string

IProperty

[interface] - Geoserver original layer properties response on DescribeFeature request

IGeoserverDescribeFeatureType

[interface] - Geoserver original response on DescribeFeature request

_parsed

DescribeFeature request parsed

Type: {namespace: string, properties: Array<IProperty>, geomType: GeometryType, geomField: string}

I18n

[interface] - Custom Language specified when creating a WFST instance

labels

Labels section

Type: {select: string?, addElement: string?, editElement: string?, save: string?, delete: string?, cancel: string?, apply: string?, upload: string?, editMode: string?, confirmDelete: string?, geomTypeNotSupported: string?, editFields: string?, editGeom: string?, selectDrawType: string?, uploadToLayer: string?, uploadFeatures: string?, validFeatures: string?, invalidFeatures: string?, loading: string?, toggleVisibility: string?, close: string?}

errors

Errors section

Type: {capabilities: string?, wfst: string?, layer: string?, layerNotFound: string?, layerNotVisible: string?, noValidGeometry: string?, geoserver: string?, badFormat: string?, badFile: string?, lockFeature: string?, transaction: string?, getFeatures: string?}

TODO

  • ~~Add support to diferent layer styles~~
  • ~~Improve widget controller: visibility toggle~~
  • ~~Add events~~
  • Add Don't show again option in the error modal
  • Allow selection of multiples features and bulk edit
  • Add customizables styles
  • Improve scss (add variables)
  • Add cookies to persist widget controller state
  • Geometry type LinearRing support
  • Tests!
  • Improve comments and documentation
  • Improve interface
  • Change svg imports to preserve svg structure
  • Improve style on editing and drawing features

About

Tiny WFS-T client to insert, modify and delete features on GeoServers using OpenLayers.

Resources

License

Stars

Watchers

Forks

Packages

No packages published