Until now we saw how we can create and
update geometries (points, polylines and polygones) using the edit and draw widgets. Using the save button we
transfer the modification to the ArcGIS server which in turn updates the SDE
database. Also important is the data entry of attribute data of a feature. I will illustrate
how we can use the attribute template widget to create a general attribute
editor for features.
The navigation within the tab control and
the accordion control inside a tab will be done with the help of custom
bindings as defined in the knockoutJS framework. As we illustrated in previous
commands, the handling of the GUI components will be kept out of the ArcGIS
framework.
2.
Attribute edit
To simplify the attribute editing we can
use the attribute inspector of the ArcGIS JavaScript API. This is a dojo widget
that covers the full editing of attributes for a feature. Depending on the
attribute field type different input editors are activated in the Dojo component.
The attribute inspector is encapsulated in
some general edit attribute method added into the GisEditing class. The only parameter needed for the tool is the list of
fields that needs to be updated. In the implementation a general editing
application, we called this method with a null value as field list. Using a
null value as field list results in adding all attribute fields of the feature. The object ID
is always masked out by the attribute inspector. and does not appears on the input form.
editAttributes: function (fieldInfos) {
try {if (currentFeatureLayer == null)
return;
currentOperation = "EditAttributes";
if (fieldInfos == null)
fieldInfos = [];
var layerInfos = [{
'featureLayer': GisOperation.getMap().getLayer(currentFeatureLayer.name),
'showDeleteButton': false,
'isEditable': true,
'fieldInfos': fieldInfos
}];
if (attributeInspector == null) {
var contentHolder = "<div id='" + attributesDiv + "'></div>";
require(["dojo/dom-construct"], function (domConstruct) {
domConstruct.place(contentHolder, "attributeDetails", "first");
});
attributeInspector = new esri.dijit.AttributeInspector({
layerInfos: layerInfos
}, attributesDiv);
dojo.connect(attributeInspector, "onAttributeChange",
function (feature, fieldName,
newFieldValue) {
//store the
updates to apply when the save button is clicked
currentFeatureLayer.getSelectedFeatures()[0].attributes[fieldName]
= newFieldValue;
});
}
this.selectFeatures();
} catch
(err) {
logging.logMessage("E", "editAttributes
failed -->" + err.message, "gisEditing");
}
},
To
include the attribute inspector widget into the web page, the best implementation I found is using the dom
contructor of the dojo library. I found
out that this is the most stable creation of this component into the
web page. This result of the display within the tabular control looks like
this:
The nice thing is that with the attribute
inspector widget , you get a rich input controls which handles the different
input data types of the feature. The
‘onAttributeChange’ event of the attribute inspector is responsible for the
update of the modified attributes into the selected feature. The attribute
inspector add also support for the usage of attachments. As you can also see,
the attribute inspector add multi language support., but as I did with Silverlight I did not add some multi language support.
3.
Move point
Although we add a separate tool button to
move a point, the implementation of the tool is exactly the same as modifying
the vertices of a polygon or polyline. In the main view model class the
implementation of the edit tools looks like this :
Edit of the vertices:
this.editExecute = function () {
editToolbarGeneralViewModel.editCommand(setEditActive);
};
this.movePointExecute = function () {
editToolbarGeneralViewModel.editCommand(setEditActive);
};
The save action has been split into the
three different actions that can be done on a feature layer, namely create, update and delete. The code
below shows that with the current API you can have the full control over editing
on feature layers and how the results are save at the ArcGIS server.
saveAll: function
() {
try {var updateGraphic;
if (currentOperation == "EditVertices") {
var graphicNew = editTool.getCurrentState();
if (graphicNew.isModified) {
updateGraphic = currentFeatureLayer.getSelectedFeatures()[0].setGeometry(graphicNew.graphic.geometry);
currentFeatureLayer.applyEdits(null, [updateGraphic], null, function (addResults, updateResults, deleteResults) {
var updateCount = updateResults.length;
}, function (err) {
logging.logMessage("E", "saveAll applyEdits failed -->" + err.message, "gisEditing");
});
}
editTool.deactivate();
}
else if (currentOperation == "EditAttributes") {
try {
attributeInspector.destroy();
attributeInspector = null;
updateGraphic = currentFeatureLayer.getSelectedFeatures()[0];
currentFeatureLayer.applyEdits(null, [updateGraphic], null, function (addResults, updateResults, deleteResults) {
var updateCount = updateResults.length;
}, function (err) {
logging.logMessage("E", "saveAll applyEdits failed -->" + err.message, "gisEditing");
});
} catch (err) {
logging.logMessage("E", "saveAll failed EditAttributes-->" + err.message, "gisEditing");
}
}
else if (currentOperation == "CreateFeature") {
if (currentGeometry != null) {
var symbol;
if (currentFeatureLayer.geometryType == "esriGeometryPolygon") {
symbol = gisOperation.getSelectionFillSymbol();
}
else if (currentFeatureLayer.geometryType == "esriGeometryPolyline") {
symbol = gisOperation.getSelectionLineSymbol();
}
else if (currentFeatureLayer.geometryType == "esriGeometryPoint") {
symbol = gisOperation.getSelectionMarkerSymbol();
}
var addGraphic = new esri.Graphic(currentGeometry, symbol, currentAttributes);
currentFeatureLayer.applyEdits([addGraphic], null, null, function (addResults, updateResults, deleteResults) {
var addCount = addResults.length;
}, function (err) {
logging.logMessage("E", "saveAll apply add failed -->" + err.message, "gisEditing");
});
}
gisOperation.getDraw().deactivate();
}
else if (currentOperation == "DeleteFeatures") {
try {
var deleteFeatures = new Array();
require(["dojo/_base/array"], function (array) {
array.forEach(currentFeatureLayer.getSelectedFeatures(), function (feature, ind) {
deleteFeatures.push(feature);
});
});
currentFeatureLayer.applyEdits(null, null, deleteFeatures, function (addResults, updateResults, deleteResults) {
var deleteCount = deleteResults.length;
}, function (err) {
logging.logMessage("E", "saveAll applyEdits failed -->" + err.message, "gisEditing");
});
} catch (err) {
logging.logMessage("E", "saveAll failed DeleteFeatures -->" + err.message, "gisEditing");
}
}
currentOperation = "";
currentAttributes = new Array();
this.clearSelectFeatures();
gisOperation.getSelectLayer().clear();
} catch (err) {
logging.logMessage("E", "saveAll failed -->" + err.message, "gisEditing")
}
},
In the save there is a lot of asynchronous
processing. By hiding this asynchronous functionality, it makes the job easier
at the GUI development. It is also important to add extensive error handling to
have a trace in case of errors occurred during the save operation.
5.
Undo modifications
As long as you did not a save with the save
button, nothing is modified on the ArcGIS server. Simply clear the graphic
layer, as it holds the modification or creation. In case of attribute update,
destroy the attribute inspector.6. Summary
In the edit tools I showed you how
you can implement some simple basis editing of feature layers. Editing,
updating or delete of feature can be performed in the same way that is done
with ArcGIS Desktop. With the attribute inspector you even get a powerful
attribute editor. In the future I hope to illustrate how you can create more
complex edit tools as already illustrated in the Silverlight ArcGIS framework
illustrated in previous documents. The basic idea will be creating basic
building blocks of editing tools that can be put together to create more
complex edit tools. This approach is not special, probably a lot of you has
already built ArcMap extensions with the main purpose to create extended edit
tools to simplify the job of GIS editors.
Based on my experience of writing ArcMap
extension for enhanced GIS editing, I will later illustrate how some of this
more complex editing tools I implemented in the past as ArcMap tools or
commands can be written as tools or commands in JavaScript as part of an ArcGIS
Application framework.
ESRI inc. did a real good job by putting an ArcGIS
API framework in place to encapsulate the REST services for the ArcGIS Server
together with the 10.01 editing functionality for feature layers. This gives us
as GIS developers an
Thank Johnny Penet,
ReplyDeleteThis article is very helpful. It saved me a lot of time. Is there any demo source code?
In the .jpg you show, how is the attribute detail area being formatted. Specifically, you show a section bijlagen. Any help there?
ReplyDeleteThanks,
i would like to save my edits directly into databse.
ReplyDeletecan we do that??
thanks in advance