I am developing an app where I display the FeatureTable for a feature class in a feature service and allow the user to edit information about features in that feature class. I am not able to perform an edit operation on a feature if the feature table for that layer has been populated. If I don't populate the feature table I can edit that feature just fine. It seems to be related to things being selected in the feature table. Click on any of the dots in the map and the first edit should work fine, then on the next one it breaks. If I select any records in the feature table first then click on a dot on the map the edit will not work at all.
I've also found that selecting features from another feature class in the map causes the edit functionality of the original feature class to break as well. All of this stuff seems very unstable, so hopefully I'm just missing something here. If this is not buggy behavior then is there a valid workflow or workaround to do this sort of thing?
I've enclosed some code that you can throw into the Javascript API sandbox so you can see the behavior I am describing. If you comment out the teamsTable.startup() line, the editing stuff will work fine.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Editable FeatureLayer with Attribute Inspector</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.15/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.15/esri/css/esri.css">
<style>
html, body, #mapDiv{
height: 100%;
width: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
#detailPane{
padding: 6px;
height:20px;
color:#570026;
font-size:12pt;
font-weight:600;
overflow: hidden;
}
.dj_ie .infowindow .window .top .right .user .content { position: relative; }
.dj_ie .simpleInfoWindow .content {position: relative;}
.esriAttributeInspector .atiLayerName {display:none;}
</style>
<script src="https://js.arcgis.com/3.15/"></script>
<script>
var map, updateFeature;
require([
"esri/map",
"esri/layers/FeatureLayer",
"esri/dijit/AttributeInspector",
"esri/dijit/FeatureTable",
"esri/symbols/SimpleLineSymbol",
"esri/symbols/SimpleMarkerSymbol",
"esri/Color",
"esri/renderers/UniqueValueRenderer",
"esri/config",
"esri/tasks/query",
"dojo/dom-construct",
"dijit/form/Button",
"dojo/on",
"dojo/domReady!"
], function(
Map, FeatureLayer, AttributeInspector, FeatureTable,
SimpleLineSymbol, SimpleMarkerSymbol, Color, UniqueValueRenderer,
esriConfig,
Query, domConstruct, Button, on
) {
// refer to "Using the Proxy Page" for more information: https://developers.arcgis.com/javascript/jshelp/ags_proxy.html
esriConfig.defaults.io.proxyUrl = "/proxy/";
map = new Map("mapDiv", {
basemap: "dark-gray",
center: [-97.395, 37.537],
zoom: 5
});
map.on("layers-add-result", initSelectToolbar);
//Feature Layer representing 2015 men's NCAA basketball tournament teams
var teamsFL = new FeatureLayer("http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/NCAA_Tourney_2015/FeatureServer/1", {
outFields: ["University", "WINPER", "Rd_64_Venue", "Rd_64_Result", "Rd_64_Margin"]
});
var selectionSymbol = new SimpleMarkerSymbol(
SimpleMarkerSymbol.STYLE_CIRCLE, 6,
new SimpleLineSymbol(
"solid",
new Color([255,0,0,0.5]),
4
),
new Color("ED3939")
);
var defaultSymbol = new SimpleMarkerSymbol(
SimpleMarkerSymbol.STYLE_CIRCLE, 7,
null,
new Color([255,255,255])
);
teamsFL.setSelectionSymbol(selectionSymbol);
//Symbolize features by W/L record
var recordRenderer = new UniqueValueRenderer(defaultSymbol, "Rd_64_Result");
recordRenderer.addValue("W", new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 7, null, new Color([93,240,79])));
recordRenderer.addValue("L", new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 7, null, new Color([240,146,79])));
teamsFL.setRenderer(recordRenderer);
map.addLayers([teamsFL]);
var teamsTable = new FeatureTable({
"featureLayer": teamsFL,
//"dateOptions": {
// "timeEnabled" : true,
// "timePattern" : "HH:mm:ss",
// "datePattern" : "YYYY-MM-DD"
//},
//"hiddenFields": ["FID", "C_Seq", "Street"], // field that end-user can show, but is hidden on startup
"map": map,
"enableLayerClick": true,
"enableLayerSelection": true
}, teamTableNode.id);
// Load event (must be before startup)
on(teamsTable, "load", function (evt) {
console.log("The load event - ", evt);
});
teamsTable.startup();
on(teamsTable, "dgrid-refresh-complete", function (evt) {
// Check record count and enable filter button accordingly
console.log("Team table dgrid-refresh-complete event - ", evt);
});
on(teamsTable, "dgrid-select", function (evt) {
console.log("Team table dgrid-select event - ", evt);
});
on(teamsTable, "dgrid-deselect", function (evt) {
console.log("Team table dgrid-deselect event - ", evt);
});
on(teamsFL, "selection-complete", function (evt) {
console.log("TEAM SELECTION COUNT: " + evt.features.length);
});
function initSelectToolbar(evt) {
var teamsFL = evt.layers[0].layer;
var selectQuery = new Query();
map.on("click", function(evt) {
selectQuery.geometry = evt.mapPoint;
selectQuery.distance = 50;
selectQuery.units = "miles"
selectQuery.returnGeometry = true;
teamsFL.selectFeatures(selectQuery, FeatureLayer.SELECTION_NEW, function(features) {
if (features.length > 0) {
//store the current feature
updateFeature = features[0];
map.infoWindow.setTitle(features[0].getLayer().name);
map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
}
else {
map.infoWindow.hide();
}
});
});
map.infoWindow.on("hide", function() {
teamsFL.clearSelection();
});
var layerInfos = [
{
'featureLayer': teamsFL,
'showAttachments': false,
'isEditable': true,
'fieldInfos': [
{'fieldName': 'University', 'isEditable': false, 'label': 'School:'},
{'fieldName': 'WINPER', 'isEditable': true, 'tooltip': 'Win percentage', 'label': 'Win percentage:'},
{'fieldName': 'Rd_64_Venue', 'isEditable': false, 'label': 'Rd 1 Venue:'},
{'fieldName': 'Rd_64_Result', 'isEditable': true, 'tooltip': 'First round result (W/L)', 'label': 'Rd 1 Result:'},
{'fieldName': 'Rd_64_Margin', 'isEditable': true, 'tooltip': 'First round margin of victory/loss', 'label': 'Rd 1 Margin:'}
]
}
];
//Initialize Attribute Inspector
var attInspector = new AttributeInspector({
layerInfos: layerInfos
}, domConstruct.create("div"));
//add a save button next to the delete button
var saveButton = new Button({ label: "Save", "class": "saveButton"},domConstruct.create("div"));
domConstruct.place(saveButton.domNode, attInspector.deleteBtn.domNode, "after");
saveButton.on("click", function() {
updateFeature.getLayer().applyEdits(null, [updateFeature], null);
});
attInspector.on("attribute-change", function(evt) {
//store the updates to apply when the save button is clicked
updateFeature.attributes[evt.fieldName] = evt.fieldValue;
});
attInspector.on("next", function(evt) {
updateFeature = evt.feature;
console.log("Next " + updateFeature.attributes.OBJECTID);
});
attInspector.on("delete", function(evt) {
evt.feature.getLayer().applyEdits(null, null, [evt.feature]);
map.infoWindow.hide();
});
map.infoWindow.setContent(attInspector.domNode);
map.infoWindow.resize(350, 240);
}
});
</script>
</head>
<body class="claro">
<div style="height:100%;width:100%;" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'">
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center', splitter:true" style="height:50%">
<div id="mapDiv"></div>
</div>
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom',splitter:true" style="height:50%">
<div style="height:100%;width:100%;" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'">
<div data-dojo-type="dijit/layout/ContentPane" id="teamDiv" style="height:90%;width:100%" data-dojo-props="region:'center', splitter:true">
<div data-dojo-attach-point="teamTableNode" id="teamTableNode" style="height:100%;width:100%;"></div>
</div>
</div>
</div>
</div>
</body>
</html>
Solved! Go to Solution.
Rickey,
That looks like good stuff man. Thanks for the heads up on this ...