<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Update FeatureLayer using applyEdits() | Sample | ArcGIS Maps SDK for JavaScript</title>
<link rel="stylesheet" href="https://js.arcgis.com/5.0/esri/themes/light/main.css" />
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.0/"></script>
.esri-item-list__scroller {
background-color: #e0e0e0;
/* override default styles */
.esri-feature-templates {
.esri-feature-templates__section-header {
.esri-feature-templates__section {
.esri-feature-templates__scroller {
const [Map, MapView, FeatureLayer, Graphic, Expand, FeatureForm, FeatureTemplates] =
"@arcgis/core/views/MapView.js",
"@arcgis/core/layers/FeatureLayer.js",
"@arcgis/core/Graphic.js",
"@arcgis/core/widgets/Expand.js",
"@arcgis/core/widgets/FeatureForm.js",
"@arcgis/core/widgets/FeatureTemplates.js",
let editFeature, highlight;
const featureLayer = new FeatureLayer({
url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/IncidentsReport/FeatureServer/0",
basemap: "dark-gray-vector",
const view = new MapView({
center: [-117.18, 34.06],
// New FeatureForm and set its layer to 'Incidents' FeatureLayer.
// FeatureForm displays attributes of fields specified in the formTemplate's field elements.
const featureForm = new FeatureForm({
map: map, // required if using Arcade expressions using the $map global variable
title: "Enter the incident number",
fieldName: "IncidentType",
label: "Choose incident type",
fieldName: "IncidentDescription",
label: "Describe the problem",
// Listen to the feature form's submit event.
// Update feature attributes shown in the form.
featureForm.on("submit", () => {
// Grab updated attributes from the form.
const updated = featureForm.getValues();
// Loop through updated attributes and assign
// the updated values to feature attributes.
Object.keys(updated).forEach((name) => {
editFeature.attributes[name] = updated[name];
// Setup the applyEdits parameter with updates.
updateFeatures: [editFeature],
applyEditsToIncidents(edits);
document.getElementById("viewDiv").style.cursor = "auto";
// Check if the user clicked on the existing feature
// The FeatureTemplates widget uses the 'addTemplatesDiv'
// element to display feature templates from incidentsLayer
const templates = new FeatureTemplates({
container: "addTemplatesDiv",
// Listen for when a template item is selected
templates.on("select", (evtTemplate) => {
// Access the template item's attributes from the event's
const attributes = evtTemplate.template.prototype.attributes;
document.getElementById("viewDiv").style.cursor = "crosshair";
// With the selected template item, listen for the view's click event and create feature
const handler = view.on("click", (event) => {
// remove click event handler once user clicks on the view
// to create a new feature
featureForm.feature = null;
const point = event.mapPoint.clone();
// Create a new feature using one of the selected
editFeature = new Graphic({
IncidentType: attributes.IncidentType,
// Setup the applyEdits parameter with adds.
addFeatures: [editFeature],
applyEditsToIncidents(edits);
document.getElementById("viewDiv").style.cursor = "auto";
console.error("event.mapPoint is not defined");
// Call FeatureLayer.applyEdits() with specified params.
function applyEditsToIncidents(params) {
// Get the objectId of the newly added feature.
// Call selectFeature function to highlight the new feature.
editsResult.addFeatureResults.length > 0 ||
editsResult.updateFeatureResults.length > 0
if (editsResult.addFeatureResults.length > 0) {
objectId = editsResult.addFeatureResults[0].objectId;
featureForm.feature = null;
objectId = editsResult.updateFeatureResults[0].objectId;
if (addFeatureDiv.style.display === "block") {
toggleEditingDivs("none", "block");
} else if (addFeatureDiv.style.display === "none") {
toggleEditingDivs("block", "none");
// show FeatureTemplates if user deleted a feature
else if (editsResult.deleteFeatureResults.length > 0) {
toggleEditingDivs("block", "none");
console.log("error = ", error);
// Check if a user clicked on an incident feature.
function selectExistingFeature() {
view.on("click", (event) => {
// clear previous feature selection
if (document.getElementById("viewDiv").style.cursor != "crosshair") {
view.hitTest(event, { include: featureLayer }).then((response) => {
// If a user clicks on an incident feature, select the feature.
if (response.results.length === 0) {
toggleEditingDivs("block", "none");
if (addFeatureDiv.style.display === "block") {
toggleEditingDivs("none", "block");
selectFeature(response.results[0].graphic.getObjectId());
// Highlights the clicked feature and display
// the feature form with the incident's attributes.
function selectFeature(objectId) {
// query feature from the server
if (results.features.length > 0) {
editFeature = results.features[0];
// display the attributes of selected feature in the form
featureForm.feature = editFeature;
// highlight the feature on the view
view.whenLayerView(editFeature.layer).then((layerView) => {
highlight = layerView.highlight(editFeature);
// Expand widget for the editArea div.
const editExpand = new Expand({
expandTooltip: "Expand Edit",
content: document.getElementById("editArea"),
view.ui.add(editExpand, "top-right");
// input boxes for the attribute editing
const addFeatureDiv = document.getElementById("addFeatureDiv");
const attributeEditing = document.getElementById("featureUpdateDiv");
// Controls visibility of addFeature or attributeEditing divs
function toggleEditingDivs(addDiv, attributesDiv) {
addFeatureDiv.style.display = addDiv;
attributeEditing.style.display = attributesDiv;
document.getElementById("updateInstructionDiv").style.display = addDiv;
// Remove the feature highlight and remove attributes
// from the feature form.
function unselectFeature() {
// Update attributes of the selected feature.
document.getElementById("btnUpdate").onclick = () => {
// Fires feature form's submit event.
// Delete the selected feature. ApplyEdits is called
// with the selected feature to be deleted.
document.getElementById("btnDelete").onclick = () => {
// setup the applyEdits parameter with deletes.
deleteFeatures: [editFeature],
applyEditsToIncidents(edits);
document.getElementById("viewDiv").style.cursor = "auto";
<div id="editArea" class="editArea-container esri-widget--panel">
<div id="addFeatureDiv" style="display: block">
<h3 class="list-heading">Report Incidents</h3>
<ul style="font-size: 13px; padding-left: 1.5em">
<li>Select template from the list</li>
<li>Click on the map to create a new feature</li>
<li>Update associated attribute data</li>
<li>Click <i>Update Incident Info</i></li>
<div id="addTemplatesDiv" style="background: #fff"></div>
<div id="featureUpdateDiv" style="display: none; margin-top: 1em">
<input type="button" class="esri-button" value="Update incident info" id="btnUpdate" />
<input type="button" class="esri-button" value="Delete incident" id="btnDelete" />
<div id="updateInstructionDiv" style="text-align: center; display: block">
<p class="or-wrap"><span class="or-text">Or</span></p>
<p id="selectHeader">Select an incident to edit or delete.</p>