Hi all,
Robert Scheitlin, GISP, Ken Buja
I have web map with editable featureLayer. After click on my feature i get atrributes (using hitTest), and after click button "Query" query result displays as graphicsLayer and after another click graphic adds to graphicLayer. Idea of doing that is to merge several features in to one feature and update featreLayer after click on button.
Now after click button "Update" i want to update graphicLayer features in my featureLayer, but it does not update.
I paste full code to show how it is done:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>GWP - მილი და სამისამართო ერთეული</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/css/main.css">
<link rel="stylesheet" href="https://code.jquery.com/ui/1.11.1/themes/smoothness/jquery-ui.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://js.arcgis.com/4.14"></script>
<script>
require([
"esri/Map",
"esri/widgets/ScaleBar",
"esri/widgets/Home",
"esri/widgets/Compass",
"esri/widgets/BasemapToggle",
"esri/symbols/SimpleMarkerSymbol",
"esri/symbols/SimpleFillSymbol",
"esri/symbols/SimpleLineSymbol",
"esri/renderers/UniqueValueRenderer",
"esri/tasks/QueryTask",
"esri/tasks/support/Query",
"esri/widgets/BasemapToggle",
"esri/widgets/DistanceMeasurement2D",
"esri/widgets/AreaMeasurement2D",
"esri/widgets/ScaleBar",
"esri/widgets/Home",
"esri/widgets/Compass",
"esri/views/MapView",
"esri/widgets/Legend",
"esri/widgets/Expand",
"esri/layers/GroupLayer",
"esri/layers/MapImageLayer",
"esri/widgets/LayerList",
"esri/layers/FeatureLayer",
"esri/layers/GraphicsLayer",
"esri/widgets/Expand",
"esri/widgets/Sketch/SketchViewModel",
"esri/widgets/FeatureForm",
"esri/widgets/FeatureTemplates",
"esri/geometry/geometryEngine",
"esri/Graphic",
"dojo/on",
"dojo/dom",
"dojo/dom-construct",
"dojo/domReady!"
], function(
Map, ScaleBar, Home, Compass, BasemapToggle, SimpleMarkerSymbol, SimpleFillSymbol, SimpleLineSymbol, UniqueValueRenderer, QueryTask, Query, BasemapToggle, DistanceMeasurement2D,
AreaMeasurement2D, ScaleBar, Home, Compass, MapView,Legend, Expand, GroupLayer, MapImageLayer,
LayerList,
FeatureLayer,
GraphicsLayer,
Expand,
SketchViewModel,
FeatureForm,
FeatureTemplates,
geometryEngine,
Graphic,
on, dom, domConstruct
) {
let editFeature, highlight;
var fLpolygonSymbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: "yellow",
style: "solid",
outline: {
color: "red",
width: 1
}
};
const featureLayer = new FeatureLayer({
url:
"http://localhost:6080/arcgis/rest/services/test/Request_Area/FeatureServer/0",
title:"",
outFields: ["*"],
popupEnabled: false,
id: "incidentsLayer",
listMode: "hide",
legendEnabled: false
});
// GraphicsLayer to hold graphics created via sketch view model
const graphicsLayer = new GraphicsLayer({
id: "tempGraphics",
listMode: "hide"
});
const labelClass = {
// autocasts as new LabelClass()
symbol: {
type: "text", // autocasts as new TextSymbol()
color: "black",
haloColor: "black",
font: {
// autocast as new Font()
family: "sans-serif",
size: 8,
weight: "bold"
}
},
labelPlacement: "center-along",
labelExpressionInfo: {
expression: "$feature.g_dasaxeleba_ka"
}
};
var renderer = {
type: "simple", // autocasts as new SimpleRenderer()
symbol: {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
style: "none",
outline: {
// makes the outlines of all features consistently light gray
color: "grey",
width: 0.5
}
}
};
layer2popup = {
title: "ქუჩა",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "g_dasaxeleba_ka",
label: "ქუჩის დასახელება",
visible: true
},{
fieldName: "SE_ID_new",
label: "SE ID new",
visible: true
},
{
fieldName: "zd_donis_ID",
label: "ზედა ზონის ID",
visible: true
}]
}]
}
var layer2 = new FeatureLayer({
url: "http://localhost:6080/arcgis/rest/services/test/Tbilisi_wyalmomarageba_vaxo/MapServer/15",
title: "სამისამართო ერთეული",
popupTemplate: layer2popup,
popupEnabled: false,
outFields: ["*"],
labelingInfo: [labelClass],
renderer: renderer
});
//saZiebo sistema
var HWUrl = "http://10.0.251.179:6080/arcgis/rest/services/test/Tbilisi_wyalmomarageba_vaxo/MapServer/15";
// magistraluri arxi
var HWLayer = new FeatureLayer({
url: HWUrl,
outFields: ["*"],
visible: false
});
/*
// GraphicsLayer for displaying results
var resultsLayer = new GraphicsLayer({
title: "ძიების რეზულტატი"
});
*/
var map = new Map({
basemap: "osm",
layers: [layer2, featureLayer, graphicsLayer]
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [44.7502, 41.725524],
zoom: 12,
highlightOptions: {
color: "red"
}
});
// Double-Click-ზე Zoom შეჩერება
view.on("double-click", function(evt) {
evt.stopPropagation();
console.info(evt);
});
// Add a basemap toggle widget to toggle between basemaps
var toggle = new BasemapToggle({
titleVisible: true,
view: view,
nextBasemap: "satellite"
});
// Toggle რუკისთვის
view.ui.add(toggle, "top-left");
// Click-ზე graphicsLayer შექმნა და მისი რუკაზე დამატება
view.on("click", function (event) {
// Search for graphics at the clicked location. View events can be used
// as screen locations as they expose an x,y coordinate that conforms
// to the ScreenPoint definition.
view.hitTest(event).then(function (response) {
if (response.results.length) {
var graphic = response.results.filter(function (result) {
// check if the graphic belongs to the layer of interest
return result.graphic.layer === layer2;
})[0].graphic;
var attributes = graphic.attributes;
var name = attributes.g_dasaxeleba_ka;
var SE_ID = attributes.SE_ID_new;
}
var queryZebna = dom.byId("query-Zebna");
on(queryZebna, "click", function() {
queryMagistraluri()
.then(displayResults);
});
function queryMagistraluri() {
var query = HWLayer.createQuery();
//query.returnGeometry = true;
//query.outFields = ["*"];
query.where = "g_dasaxeleba_ka LIKE N'%"+ name +"%'";
query.outSpatialReference = view.spatialReference;
return HWLayer.queryFeatures(query)
}
// display the query results in the view
function displayResults(results) {
console.log(results);
var pfeatures = results.features.map(function(graphica) {
graphica.symbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: "orange",
style: "solid",
outline: { // autocasts as new SimpleLineSymbol()
color: "black",
width: 1
}
};
return graphica
});
graphicsLayer.addMany(pfeatures);
view.goTo(pfeatures)
}
});
});
const btnupdate = dom.byId("button-update");
on(btnupdate, "click", function () {
// Create a new graphic and set its geometry to
function addGraphic(event) {
// Create a new graphic and set its geometry to
// `create-complete` event geometry.
const graphic = new Graphic({
geometry: polygon,
symbol: graphica.symbol,
attributes: {}
});
graphicsLayer.add(graphic);
const edits = { //Fire the addFeatures function using the completed graphic
addFeatures: [graphic]
};
applyEdits(edits);
console.log(graphic);
};
function applyEdits(params) {
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;
}
})
.catch(function(error) {
console.log("===============================================");
console.error("[ applyEdits ] FAILURE: ", error.code, error.name,
error.message);
console.log("error = ", error);
});
}
})
});
</script>
</head>
<body>
<button id="query-Zebna">ძებნა</button>
<button id="button-update">Update</button>
<div id="viewDiv"></div>
</div>
</body>
</html>
Solved! Go to Solution.
Vakhtang,
You are attempting to add a GraphicsLayer as the addFeatures property of the applyEdits method and that is the issue. The applyEdits addFeatures property is expecting and array of graphics.
const edits = { //Fire the addFeatures function using the completed graphic addFeatures:
pfeatures
};
Vakhtang,
This portion of your code make no sense. You have a button click event function whose contents is just two other functions... But nothing calls addGraphic.
const btnupdate = dom.byId("button-update");
on(btnupdate, "click", function () {
// Create a new graphic and set its geometry to
function addGraphic(event) {
// Create a new graphic and set its geometry to
// `create-complete` event geometry.
const graphic = new Graphic({
geometry: polygon,
symbol: graphica.symbol,
attributes: {}
});
graphicsLayer.add(graphic);
const edits = { //Fire the addFeatures function using the completed graphic
addFeatures: [graphic]
};
applyEdits(edits);
console.log(graphic);
};
function applyEdits(params) {
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;
}
})
.catch(function (error) {
console.log("===============================================");
console.error("[ applyEdits ] FAILURE: ", error.code, error.name,
error.message);
console.log("error = ", error);
});
}
});
Robert,
I see
I changed my code, now it applies empty attributes without geometry.
Also if i do not mistake i already have defined graphic here (see row 24), can i use it for update graphics layer? if so, how?
If no: How can i call "create-complete" for addGraphic? From this Query? "var query = HWLayer.createQuery();" tell me how please.
P.S. Sorry for my bad skills, i study JavaScript myself and sometimes it is hard to connect some portion of code to next part. Thank you for your help, i really appreciate.
view.on("click", function (event) {
view.hitTest(event).then(function (response) {
if (response.results.length) {
var graphic = response.results.filter(function (result) {
// check if the graphic belongs to the layer of interest
return result.graphic.layer === layer2;
})[0].graphic;
var attributes = graphic.attributes;
var name = attributes.Req_Code; }
var queryZebna = dom.byId("query-Zebna");
on(queryZebna, "click", function() {
queryMagistraluri()
.then(displayResults);});
function queryMagistraluri() {
var query = HWLayer.createQuery();
//query.returnGeometry = true;
//query.outFields = ["*"];
query.where = "Req_Code IS NULL";
query.outSpatialReference = view.spatialReference;
return HWLayer.queryFeatures(query)}
// display the query results in the view
function displayResults(results) {
console.log(results);
var pfeatures = results.features.map(function(graphica) {
graphica.symbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: "cyan",
style: "solid",
outline: { // autocasts as new SimpleLineSymbol()
color: "black",
width: 1
},
};
return graphica
});
graphicsLayer.addMany(pfeatures);
console.log(graphicsLayer)
// Apply Edits აქ მუშაობს, მაგრამ მხოლოდ ამატებს ატრიბუტებს.
const edits = { //Fire the addFeatures function using the completed graphic
addFeatures: [graphicsLayer]
};
applyEdits(edits);
console.log(graphic);
view.goTo(pfeatures)
}
})
})
Vakhtang,
You are attempting to add a GraphicsLayer as the addFeatures property of the applyEdits method and that is the issue. The applyEdits addFeatures property is expecting and array of graphics.
const edits = { //Fire the addFeatures function using the completed graphic addFeatures:
pfeatures
};
Robert,
Thank you very much for help.
I do not kmow if i have to open new question. but i ask here and if needed i will open new question.
When adding new features from one to another layer using this code, one field has same name and it values adds automaticaly from source layer (Layer2) to target layer (featureLayer). So i tried to add attributes with same name to graphics (pfeatures) as it has target layer (featureLayer)(e.g. field name "Req_Code") and add value e.g. "REQ-123", but it does not applies. in console.log it returns -, Req_Code: REQ-123".
Code:
pfeatures = results.features.map(function(graphica) {
graphica.symbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: "cyan",
style: "solid",
outline: { // autocasts as new SimpleLineSymbol()
color: "black",
width: 1
},
};
pfeatures.attributes{
Req_Code:"REQ-123"
}
console.log(pfeatures)
Vakhtang,
pFeatures is an Array of graphics you can not set an attribute on the whole array that way. You need to apply the attribute to one graphic.
Robert,
I tryied to merge graphics using geometryEngine.union, but had no result. How can i merge (dissolve, union) pfeatures array in one graphic?
When using GeometryEngine.union make sure you are passing the geometries to it and not the graphics
Oops, you guessed right, i passed graphics. that is why i got "null" in
log.
Can you please explain how can i pass geometry or point me Sample or
something like that?
On Tue, Jan 28, 2020, 11:54 PM Robert Scheitlin, GISP <geonet@esri.com>
Each Graphic has a geometry property.