Skip to main content

FeatureService

Integrates ArcGIS Feature Services with MapLibre GL JS and Mapbox GL JS. Provides vector data with smart vector tile detection, GeoJSON fallback, server-side filtering, feature editing, and attachments.

Live Demo

Interactive example showing FeatureService with various ArcGIS Feature Services

Quick Start

import { FeatureService } from 'esri-gl';

const featureService = new FeatureService('features-source', map, {
url: 'https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0'
});

map.addLayer({
id: 'features-layer',
type: 'circle',
source: 'features-source',
paint: {
'circle-radius': 5,
'circle-color': '#007cbf',
'circle-stroke-width': 1,
'circle-stroke-color': '#ffffff'
}
});

Constructor

ArgumentTypeDescription
idstringAn id to assign to the MapLibre GL source
mapMapA MapLibre GL or Mapbox GL map instance
esriServiceOptionsobjectOptions for the Feature Service (see below)
geoJsonSourceOptionsobjectOptional MapLibre GL GeoJSON source options

Options

OptionTypeDefaultDescription
urlstringRequired. URL of the FeatureService layer
wherestring'1=1'SQL WHERE clause to filter features
outFieldsArray<string> | string'*'Fields to include in response
geometryobjectGeometry to spatially filter features
geometryTypestringType of geometry filter
spatialRelstring'esriSpatialRelIntersects'Spatial relationship
outSRnumber4326Output spatial reference
returnGeometrybooleantrueInclude geometry in response
maxRecordCountnumberMaximum features to return
resultOffsetnumberStarting record for pagination
orderByFieldsstringFields to sort results by
tokenstringAuthentication token (URL parameter)
apiKeystringAPI key for X-Esri-Authorization header auth
fetchOptionsobjectFetch request options
useVectorTilesbooleanfalseEnable smart vector tile detection with GeoJSON fallback
useBoundingBoxbooleantrueEnable viewport-based data loading for performance

Methods

MethodReturnsDescription
query(options?)Promise<GeoJSON.FeatureCollection>Query features with custom parameters
updateQuery(options)voidUpdate query parameters and refresh
refresh()voidRefresh data from service
setBoundingBox(enabled)voidEnable/disable bounding box filtering
identify(lngLat, returnGeometry?)Promise<IdentifyResult[]>Identify features at a point
remove()voidRemove service and clean up resources

Editing Methods

Methods for creating, updating, and deleting features on editable Feature Services.

addFeatures(features, options?)

ParameterTypeDescription
featuresGeoJSON.Feature[]Features to add
options{ gdbVersion?: string }Optional geodatabase version

Returns: Promise<EditResult[]>

updateFeatures(features, options?)

ParameterTypeDescription
featuresGeoJSON.Feature[]Features to update (must include OBJECTID)
options{ gdbVersion?: string }Optional geodatabase version

Returns: Promise<EditResult[]>

deleteFeatures(params)

ParameterTypeDescription
params.objectIdsnumber[]Object IDs to delete
params.wherestringSQL WHERE clause to select features for deletion

Returns: Promise<EditResult[]>

applyEdits(edits, options?)

ParameterTypeDescription
edits.addsGeoJSON.Feature[]Features to add
edits.updatesGeoJSON.Feature[]Features to update
edits.deletesnumber[]Object IDs to delete
options{ gdbVersion?: string }Optional geodatabase version

Returns: Promise<ApplyEditsResult>

const service = new FeatureService('editable-source', map, {
url: 'https://services.arcgis.com/.../FeatureServer/0',
token: 'your-agol-token'
});

// Batch edits in a single request
const results = await service.applyEdits({
adds: [{
type: 'Feature',
geometry: { type: 'Point', coordinates: [-118.24, 34.05] },
properties: { name: 'Los Angeles' }
}],
updates: [{
type: 'Feature',
geometry: { type: 'Point', coordinates: [-118.24, 34.05] },
properties: { OBJECTID: 1, population: 4000000 }
}],
deletes: [10, 11, 12]
});

Attachment Methods

queryAttachments(objectId, options?)

ParameterTypeDescription
objectIdnumberObject ID of the feature

Returns: Promise<AttachmentInfo[]>

addAttachment(objectId, file, fileName?)

ParameterTypeDescription
objectIdnumberObject ID of the feature
fileBlob | FileThe file to attach
fileNamestringOptional file name

Returns: Promise<EditResult>

deleteAttachments(objectId, attachmentIds)

ParameterTypeDescription
objectIdnumberObject ID of the feature
attachmentIdsnumber[]IDs of attachments to delete

Returns: Promise<EditResult[]>

Events

EventDescription
authenticationrequiredFired when the service receives a 498/499 auth error. ArcGIS Online returns these as HTTP 200 with a JSON error body; the service detects and surfaces them automatically.
service.on('authenticationrequired', async (error) => {
const newToken = await refreshToken();
service.setToken(newToken);
});

Examples

Smart Vector Tile Detection

const service = new FeatureService('smart-source', map, {
url: 'https://services.arcgis.com/.../FeatureServer/0',
useVectorTiles: true // Detects vector tile support, falls back to GeoJSON
});

Server-Side Filtering

const filtered = new FeatureService('filtered-source', map, {
url: 'https://services.arcgis.com/.../FeatureServer/0',
where: "SPECIES = 'Oak' AND HEIGHT > 20",
outFields: 'SPECIES,HEIGHT,DIAMETER'
});

Automatic Styling with getStyle()

Returns a layer style matching the service geometry type (circle for points, line for lines, fill for polygons). For vector tile sources, includes the appropriate source-layer.

const layerStyle = await featureService.getStyle();
map.addLayer({ id: 'auto-styled-layer', ...layerStyle });

Authentication

// Token auth (URL parameter)
const service = new FeatureService('source', map, {
url: 'https://services.arcgis.com/.../FeatureServer/0',
token: 'your-auth-token'
});

// API key auth (X-Esri-Authorization header)
const service2 = new FeatureService('source', map, {
url: 'https://services.arcgis.com/.../FeatureServer/0',
apiKey: 'your-api-key'
});

// Update token dynamically
service.setToken('refreshed-token');