概述
本篇示例展示,如何使用FeatureLayer.applyEdits()添加新的要素,更新现有要素的属性和删除要素。本文使用FeatureTemplates组件展示可编辑的要素图层的template。组件监听最终用户选择的组件中的模板,它的select事件被触发,并返回结果模板信息。
除了FeatureTemplates组件,本文还使用了FeatureForm组件用于编辑要素的属性。
// Call FeatureLayer.applyEdits() with specified params.
function applyEdits(params) {
addFeatureBtnDiv.style.display = "none";
addTemplatesDiv.style.display = "none";
unselectFeature();
featureLayer
.applyEdits(params)
.then(function(editsResult) {
// Get the objectId of the newly added feature.
// Call selectFeature function to highlight the new feature.
if (editsResult.addFeatureResults.length > 0) {
const objectId = editsResult.addFeatureResults[0].objectId;
selectFeature(objectId);
}
})
.catch(function(error) {
console.log("===============================================");
console.error("[ applyEdits ] FAILURE: ", error.code, error.name, error.message);
console.log("error = ", error);
});
}
FeatureLayer.applyEdits()返回一个对象包含edit results.如果编辑失败, 结果中包含错误信息。
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<!--
ArcGIS API for JavaScript, https://js.arcgis.com
For more information about the editing-applyedits sample, read the original sample description at developers.arcgis.com.
https://developers.arcgis.com/javascript/latest/sample-code/editing-applyedits/index.html
-->
<title>Update FeatureLayer using applyEdits() - 4.11</title>
<link rel="stylesheet"
href="https://js.arcgis.com/4.11/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.11/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
.esri-item-list__scroller {
overflow-y: visible;
}
.editArea-container {
background: #fff;
font-family: "Avenir Next W00", "Helvetica Neue", Helvetica, Arial, sans-serif;
line-height: 1.5em;
overflow: auto;
padding: 12px 15px;
width: 300px;
}
.list-heading {
font-weight: normal;
margin-top: 20px;
margin-bottom: 10px;
color: #323232;
}
.or-wrap {
background-color: #e0e0e0;
height: 1px;
margin: 2em 0;
overflow: visible;
}
.or-text {
background: #fff;
line-height: 0;
padding: 0 1em;
position: relative;
bottom: 0.75em;
}
/* override default styles */
.esri-feature-form {
background: #fff;
}
.esri-feature-templates {
width: 256px;
}
.esri-feature-templates__section-header {
display: none;
}
.esri-feature-templates__section {
box-shadow: none;
}
.esri-feature-templates__scroller {
max-height: 200px;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/Graphic",
"esri/widgets/Expand",
"esri/widgets/FeatureForm",
"esri/widgets/FeatureTemplates"
], function (
Map,
MapView,
FeatureLayer,
Graphic,
Expand,
FeatureForm,
FeatureTemplates
) {
let editFeature, highlight;
const featureLayer = new FeatureLayer({
url:
"https://services.arcgis.com/V6ZHFr6zdgNZuVG0/ArcGIS/rest/services/IncidentsReport/FeatureServer/0",
outFields: ["*"],
popupEnabled: false,
id: "incidentsLayer"
});
const map = new Map({
basemap: "dark-gray",
layers: [featureLayer]
});
const view = new MapView({
container: "viewDiv",
map: map,
center: [-117.18, 34.06],
zoom: 15
});
// New FeatureForm and set its layer to 'Incidents' FeatureLayer.
// FeatureForm displays attributes of fields specified in fieldConfig.
const featureForm = new FeatureForm({
container: "formDiv",
layer: featureLayer,
fieldConfig: [
{
name: "IncidentType",
label: "Choose incident type"
},
{
name: "IncidentDescription",
label: "Describe the problem"
}
]
});
// Listen to the feature form's submit event.
// Update feature attributes shown in the form.
featureForm.on("submit", function () {
if (editFeature) {
// 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(function (name) {
editFeature.attributes[name] = updated[name];
});
// Setup the applyEdits parameter with updates.
const edits = {
updateFeatures: [editFeature]
};
applyEditsToIncidents(edits);
document.getElementById("viewDiv").style.cursor = "auto";
}
});
// Check if the user clicked on the existing feature
selectExistingFeature();
// The FeatureTemplates widget uses the 'addTemplatesDiv'
// element to display feature templates from incidentsLayer
const templates = new FeatureTemplates({
container: "addTemplatesDiv",
layers: [featureLayer]
});
// Listen for when a template item is selected
templates.on("select", function (evtTemplate) {
// Access the template item's attributes from the event's
// template prototype.
attributes = evtTemplate.template.prototype.attributes;
unselectFeature();
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", function (event) {
// remove click event handler once user clicks on the view
// to create a new feature
handler.remove();
event.stopPropagation();
featureForm.feature = null;
if (event.mapPoint) {
point = event.mapPoint.clone();
point.z = undefined;
point.hasZ = false;
// Create a new feature using one of the selected
// template items.
editFeature = new Graphic({
geometry: point,
attributes: {
IncidentType: attributes.IncidentType
}
});
// Setup the applyEdits parameter with adds.
const edits = {
addFeatures: [editFeature]
};
applyEditsToIncidents(edits);
document.getElementById("viewDiv").style.cursor = "auto";
} else {
console.error("event.mapPoint is not defined");
}
});
});
// Call FeatureLayer.applyEdits() with specified params.
function applyEditsToIncidents(params) {
// unselectFeature();
featureLayer
.applyEdits(params)
.then(function (editsResult) {
// Get the objectId of the newly added feature.
// Call selectFeature function to highlight the new feature.
if (
editsResult.addFeatureResults.length > 0 ||
editsResult.updateFeatureResults.length > 0
) {
unselectFeature();
let objectId;
if (editsResult.addFeatureResults.length > 0) {
objectId = editsResult.addFeatureResults[0].objectId;
} else {
featureForm.feature = null;
objectId = editsResult.updateFeatureResults[0].objectId;
}
selectFeature(objectId);
if (addFeatureDiv.style.display === "block") {
toggleEditingDivs("none", "block");
}
}
// show FeatureTemplates if user deleted a feature
else if (editsResult.deleteFeatureResults.length > 0) {
toggleEditingDivs("block", "none");
}
})
.catch(function (error) {
console.log("===============================================");
console.error(
"[ applyEdits ] FAILURE: ",
error.code,
error.name,
error.message
);
console.log("error = ", error);
});
}
// Check if a user clicked on an incident feature.
function selectExistingFeature() {
view.on("click", function (event) {
// clear previous feature selection
unselectFeature();
if (
document.getElementById("viewDiv").style.cursor != "crosshair"
) {
view.hitTest(event).then(function (response) {
// If a user clicks on an incident feature, select the feature.
if (response.results.length === 0) {
toggleEditingDivs("block", "none");
} else if (
response.results[0].graphic &&
response.results[0].graphic.layer.id == "incidentsLayer"
) {
if (addFeatureDiv.style.display === "block") {
toggleEditingDivs("none", "block");
}
selectFeature(
response.results[0].graphic.attributes[
featureLayer.objectIdField
]
);
}
});
}
});
}
// Highlights the clicked feature and display
// the feature form with the incident's attributes.
function selectFeature(objectId) {
// query feature from the server
featureLayer
.queryFeatures({
objectIds: [objectId],
outFields: ["*"],
returnGeometry: true
})
.then(function (results) {
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(function (layerView) {
highlight = layerView.highlight(editFeature);
});
}
});
}
// Expand widget for the editArea div.
const editExpand = new Expand({
expandIconClass: "esri-icon-edit",
expandTooltip: "Expand Edit",
expanded: true,
view: view,
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() {
if (highlight) {
highlight.remove();
}
}
// Update attributes of the selected feature.
document.getElementById("btnUpdate").onclick = function () {
// Fires feature form's submit event.
featureForm.submit();
};
// Delete the selected feature. ApplyEdits is called
// with the selected feature to be deleted.
document.getElementById("btnDelete").onclick = function () {
// setup the applyEdits parameter with deletes.
const edits = {
deleteFeatures: [editFeature]
};
applyEditsToIncidents(edits);
document.getElementById("viewDiv").style.cursor = "auto";
};
});
</script>
</head>
<body>
<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>
</ul>
<div id="addTemplatesDiv" style="background:#fff;"></div>
</div>
<div id="featureUpdateDiv" style="display:none; margin-top: 1em;">
<h3 class="list-heading">Enter the incident information</h3>
<div id="attributeArea">
<div id="formDiv"></div>
<input type="button"
class="esri-button"
value="Update incident info"
id="btnUpdate" />
</div>
<br />
<div id="deleteArea">
<input type="button"
class="esri-button"
value="Delete incident"
id="btnDelete" />
</div>
</div>
<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>
</div>
</div>
<div id="viewDiv"></div>
</body>
</html>