By default, custom data providers created using the CDF command line tool include only query capabilities. However, you can extend a custom data provider to implement the apply
operation on the custom data feature service by defining custom routes and methods.
After creating a custom data provider with the CDF command line tool, follow the steps below to configure it for edit capability.
Configuring Provider Routes and Controllers
-
Create a new file called routes.js in the providers/your_provider_name/src directory. Add the following code to the file:
Use dark colors for code blocks Copy module.exports = [ { path: `/<provider_name>/rest/services/:host/:id/FeatureServer/:layer/applyEdits`, methods: ['POST'], handler: 'editData' }, { path: `/<provider_name>/rest/services/:host/:id/FeatureServer/applyEdits`, methods: ['POST'], handler: 'editData' } ]
In this file, we've created two new routes - one for layer-level editing requests and one for service-level editing requests. These routes follow the same pattern as the read-only
query
routes but have theapply
operation instead. If your custom data provider makes use ofEdits host
andid
path parameters, make sure these are present in the newly registered routes.apply
is an HTTPEdits POST
method. The value of thehandler
property refers the name of the function that your custom data code will execute when this route recieves a request. In this case the function name isedit
, but this can be any name you choose.Data -
Create a new file called controllers.js in the providers/your_provider_name/src directory. Add
the following code to the file:Use dark colors for code blocks Copy function Controller (model) { this.model = model } Controller.prototype.editData = async function (req, res) { const pathParams = req.params; const body = req.body; const reply = await this.model.editData(pathParams, body); res.status(200).json(reply); } module.exports = Controller
In the file, we've registerd our
handler
functionedit
. The request path parameters and the request body are passed intoData edit
. AfterData edit
executes its editing logic, the reply is returned.Data -
Open the file index.js in the providers/your_provider_name/src directory. Add the two lines (
routes
andController
) shown in the code below to theprovider
object.Use dark colors for code blocks Copy const packageInfo = require('../package.json') const csconfigInfo = require('../cdconfig.json') const provider = { type: csconfigInfo.type, name: csconfigInfo.name, version: packageInfo.version, hosts: csconfigInfo.properties.hosts, disableIdParam: csconfigInfo.properties.disableIdParam, Model: require('./model'), routes: require('./routes'), Controller: require('./controllers') } module.exports = provider
At this point, the provider is configured to handle editing requests via the
apply
route. The next step is write the custom code for performing edits on the remote data source in theEdits edit
function.Data -
Open the model.js file in the providers/your_provider_name/src directory. In the
Model
class, create a newedit
function. At this point, the code becomes specific to your implementation. Below is a sample of a basicData edit
function that calls on various helper functions.Data Use dark colors for code blocks Copy async editData(pathParams, body) { // assign database and collection name from path parameters const databaseName = pathParams.host; const collectionName = pathParams.id; // add logic to normalize layer-level or service-level requests const extractedEdits = normalizeRequestedEdits(body); const database = this.#client.db(databaseName); const collection = database.collection(collectionName); let applyEditsResponse = {} // initialize the response object // call the necessary functions to handled the edits applyEditsResponse = await performEdits(collection, extractedEdits.edits); // check if the response should be an object(layer-level) or an array(service-level) if (extractedEdits.editLevel === 'service') { applyEditsResponse.id = extractedEdits.layer; return [applyEditsResponse]; } return applyEditsResponse; }
Understanding the apply Edits
API Specification
The edit
method must be written to handle requests and return responses that conform to the apply
REST API specification. To ensure compatibility with ArcGIS clients, the edit
method should be designed to handle both layer-level and service-level apply
requests.
A high-level overview of the specification is provided below. For complete details on the structure of requests and responses, refer to the REST API specification. Additionally, see this Walkthrough topic for an example of how to implement these details in a custom data provider.
Layer-level Request
The request object for a layer-level apply
operation includes three optional parameters: adds
, updates
, deletes
, with at least one of these present. Each parameter is an array:
adds
andupdates
: Arrays of objects where each objects containsgeometry
and/orattributes
.deletes
: Either a comma-separated string of object IDs or an array of object IDs.
Example:
adds:
[
{
"geometry": {
"x": -12246623.482500909,
"y": 6274905.896395514,
"spatialReference": {
"wkid": 102100,
"latestWkid": 3857
}
},
"attributes": {
"fireId": "C3PO",
"fireName": "Golden Fire",
"fireType": "Wild",
"acres": "4682"
}
}
]
Layer-level Response
The response object for a layer-level apply
operation includes three arrays: add
, update
, and delete
. Each array contains objects that minimally include the object
and a success
status (true
or false
). The arrays may be empty if no edits were requested.
Example:
{
"addResults": [
{
"objectId": 621431404,
"success": true
}
],
"updateResults": [],
"deleteResults": []
}
Service-level Request
The request object for a service-level apply
operation includes a required edits
parameter, which is an array of layer objects. Each layer object contains the following arrays:
adds
andupdates
: Arrays of objects where each object includesgeometry
and/orattributes
.deletes
: Either an array of object IDs or a comman-separated string of object IDs.
If no edit is requested for a particular type (adds
, updates
, or deletes
), its value will be null
.
Example:
edits:
[
{
"id": 0,
"adds": null,
"updates": [
{
"geometry": {
"spatialReference": {
"wkid": 102100
},
"x": -12700718.995399643,
"y": 6622215.403721428
},
"attributes": {
"alternateID": 3
}
}
],
"deletes": null,
"attachments": null,
"assetMaps": null
}
]
Service-level Response
The response for a service-level apply
operation is an array of layer objects. Each layer object includes the following arrays:
add
,Results update
, andResults delete
: Each array contains objects that minimally include theResults object
and aID success
status (true
orfalse
).
If no edits were requested, these arrays may be empty.
Example:
[
{
"id": 0,
"addResults": [],
"updateResults": [
{
"success": true,
"objectId": 3
}
],
"deleteResults": []
}
]
Important Points
Custom data providers with edit capability require additional considerations for maintaining data integrity and accessibilty. At a minimum, this involves understanding the spatial reference and data structure of the remote data source. The metadata provided with the returned GeoJSON in the provider will also impact which attributes are editable and influence how ArcGIS clients configure editing widgets.
Spatial Reference
Your provider code should track the spatial reference of the remote data source. Once data are sent to the client, reprojections may occur based on the client’s default behavior or user preferences. Edits may be requested in a spatial reference that differs from the data source. It is highly recommended that your code compares the spatial references and, when they differ, transforms the data back to the original spatial reference. For transofrmation, use @esri/proj-codes and proj4. This process is demonstrated in this Walkthrough.
ObjectId
To be editable, features in the remote data source must include an attribute that meets the requirements for an esri
. This attribute must be an integer no larger than 64 bits. For detials, refer to the CDF API Reference documentation on the id
metadata property.
Templates
Templates are essential for customizing editing widgets in ArcGIS clients. By using custom templates, you can specify which attributes are visible for editing, set default values, and apply other customizations. Refer to the CDF API Reference documentation on the templates
metadata property.
fields
Metadata
To make an attribute editable, set the editable
property in the fields
metadata. This allows fine-grained control over which feature attributes are available for editing. See the CDF API Reference documentation on the fields
metadata property.