add items to map, collectively, one at a time, per attribute id

881
20
Jump to solution
06-20-2020 05:50 PM
CamCode
New Contributor III
I have successfully been able to filter, for instance shakemaps, by attribute id - I have successfully achieved this multiple ways - but all ending with the same problem.

1.) with the where filter 2.) definition expression 3.) iterating through all attribute ids and bringing them back.

The problem: All exists for only allowing/displaying one per attribute id at a time.. my goal is to feed the attribute ids into a checkbox list (which I have done), but allowing for items via attribute id to be added to the map as they are checked, collectively, one at a time - currently I can not seem to get this to work with the aspect of having multiple or more then one appear at a time on the map - each filter or attempt results in the next item being added while at the same time the previous is replaced (only showing one at a time).

1.) i.e. the below filter (attempted logic 1) - & also here is CodePen of:

.....         function filterByID(event) {           const selectedID = event.target.getAttribute("data-id");             eqLayerView.filter = {             where: "id = '" + selectedID + "'"           };         }          view.whenLayerView(fl)           .then(function(layerView) {            eqLayerView = layerView;            eqLayerView.filter = {             where: "id = ''"           };.............

2.) i.e. another attempted logic (adding multiple at a time here, line by line, or via array):

layer.definitionExpression = "id = 'us70008jr5'",layer.definitionExpression = "id = 'cgi988jr52'",

3.) i.e. 3rd attempt with a suggestion here on GIS exchange: Loop through attribute ids of FeatureLayer

layer   .load()  .then(() => {    // create a query from the layer    const query = layer.createQuery();    query.returnDistinctValues = true;    query.where = "grid_value > 2"; // or 1=1 if you need them all    // the field you want distinct values for    query.outFields = ["id"];    return layer.queryFeatures(query);  })  .then(({ features }) => {    // extract the ids to a list    const ids = features.map(({ attributes }) => attributes.id);    return ids;  })  .then((ids) => {    // You can store them how you want, in this case,    // I put them in a dropdown select menu    const fragment = document.createDocumentFragment();    ids.forEach((id) => {      const option = document.createElement('option');      option.value = id;      option.innerText = id;      fragment.appendChild(option);    });    list.appendChild(fragment);    map.add(layer);});

All attempted logic above result in the toggling of a shakemap by attribute id to be displayed only one at a time — by toggling a new on, the previous turns off, I need the ability to have multiple being able to exist on the map at once.

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Esteemed Contributor

Updated code to ensure only unique vals added as checkboxes.

Cam,

  Here is my changes to your code.

  • If you just need to query a service for the data then do not use a FeatureLayer just for that.
  • no need for a GraphicsLayer at all if you are just adding the graphics to a client side FeatureLayer
  • The filter need to applied to your client side FeatureLayer.
<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<title>ArcGIS JavaScript Tutorials: Add layers to a map</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}

.contn {
position: absolute;
bottom: 0px;
left: 0px;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.15/esri/themes/light/main.css">
<script src="https://js.arcgis.com/4.15/"></script>

<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/geometry/geometryEngine",
"esri/geometry/Circle",
"esri/Graphic",
"esri/symbols/SimpleFillSymbol",
"esri/renderers/ClassBreaksRenderer",
"esri/widgets/Legend",
"esri/tasks/QueryTask",
"esri/tasks/support/Query"
], function (
Map,
MapView,
FeatureLayer,
geometryEngine,
Circle,
Graphic,
SimpleFillSymbol,
ClassBreaksRenderer,
Legend,
QueryTask,
Query) {

var map = new Map({
basemap: "gray"
});

var view = new MapView({
container: "viewDiv",
map: map,
center: [-122, 37],
zoom: 2
});

let eqLayerView;
let fl;
let gras = [];
let dVals = [];

let QT = new QueryTask({
url: "https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/USGS_Seismic_Data_v1/FeatureServer/1"
});
let query = new Query();
query.where = "eventTime >= CURRENT_TIMESTAMP - 30 AND grid_value > 2";
query.outFields = ["id"];
query.returnDistinctValues = true;
query.returnGeometry = false;
query.orderByFields =["id"];
QT.execute(query).then(function (results) {
results.features.map(function (feat) {
let id = feat.attributes["id"];
if(dVals[id] === undefined){
dVals[id] = true;
let opt = document.createElement("input");
opt.type = "checkbox";
let label = document.createElement('label')
label.innerHTML = id;
opt.className = "id-item visible-id shakeids";
opt.setAttribute("data-id", id);
opt.name = "shaks";

idElement.appendChild(opt);
idElement.appendChild(label);

getCur(event);
}
});
}).catch(function(err){
console.error(err);
});

function getCur(event) {
let chkst = document.querySelector('.shaked');
if (chkst) {
chkst.addEventListener("click", filterByID);
} else {
getCur();
}
}

query.outFields = ["*"];
query.returnDistinctValues = false;
query.returnGeometry = true;
QT.execute(query).then(function (evt) {
evt.features.forEach(function (feature) {
var att = feature.attributes
var test = geometryEngine.convexHull(feature.geometry)
var genpoly = null
if (att.grid_value <= 4.0) {
var rad = att.Shape__Length / 75
genpoly = new Circle({
center: test.centroid,
radius: rad,
radiusUnit: "meters"
})
} else {
genpoly = test
}
var polygonGraphic = new Graphic({
geometry: genpoly,
attributes: att,
type: "polygon"
});
gras.push(polygonGraphic);
});
var renderer = {
type: "class-breaks",
field: "grid_value",
classificationMethod: "esriClassifyManual",
classBreakInfos: [{
minValue: 0,
maxValue: 1.9999,
symbol: {
color: [0, 0, 0, 0],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "I (Not Felt)"
},
{
minValue: 2.0,
maxValue: 3.0,
symbol: {
color: [191, 204, 255, .3],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "II (Weak)"
},
{
minValue: 3.1,
maxValue: 3.9,
symbol: {
color: [153, 153, 255, .4],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "III (Weak)"
},
{
minValue: 4.0,
maxValue: 4.5,
symbol: {
color: [136, 255, 255, 1],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "IV (Light)"
},
{
minValue: 4.5,
maxValue: 4.9999,
symbol: {
color: [125, 248, 148, 1],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "V (Light)"
},
{
minValue: 6.0,
maxValue: 6.9999,
symbol: {
color: [255, 255, 0, 1],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "VI (Strong)"
},
{
minValue: 7.0,
maxValue: 7.9999,
symbol: {
color: [255, 221, 0, 1],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "VII (Very Strong)"
},
{
minValue: 8.0,
maxValue: 8.9999,
symbol: {
color: [255, 145, 0, 1],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "VIII (Severe) "
},
{
minValue: 9.0,
maxValue: 9.9999,
symbol: {
color: [255, 0, 0, 1],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "IX (Violent)"
},
{
minValue: 10.0,
maxValue: 10.9999,
symbol: {
color: [221, 0, 0, 1],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "X"
},
{
minValue: 11.0,
maxValue: 11.9999,
symbol: {
color: [136, 0, 0, 1],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "XI"
},
{
minValue: 12.0,
maxValue: 12.0,
symbol: {
color: [68, 0, 0, 1],
outline: {
color: [0, 0, 0, 0],
width: 0.4,
type: "simple-line",
style: "solid"
},
type: "simple-fill",
style: "solid"
},
label: "XII"
}
]
}
var popuptemp = {
title: "Shake Intensity",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "grid_value",
label: "Grid Value"
},
{
fieldName: "id",
label: "id"
},
{
fieldName: "ObjectID",
label: "ObjectID"
},
{
fieldName: "url",
label: "Url"
}
]
}]
}
fl = new FeatureLayer({
source: gras,
objectIdField: "ObjectID",
geometryType: "polygon",
fields: [{
name: "ObjectID",
alias: "ObjectID",
type: "oid"
}, {
name: "id",
alias: "id",
type: "string"
}, {
name: "url",
alias: "url",
type: "string"
}, {
name: "grid_value",
alias: "grid_value",
type: "double"
}],
renderer: renderer,
popupEnabled: true,
popupTemplate: popuptemp
});
map.add(fl);

view.whenLayerView(fl).then(function (layerView) {
eqLayerView = layerView;
eqLayerView.filter = {
where: "id = ''"
};
});
});

let quakeFoldr = document.getElementById("Shakemaps").parentElement;
let onup = quakeFoldr.parentElement;
let twup = onup.parentElement;

let idElement = document.createElement("div");
let isElement = document.createElement("ul");

idElement.className += "shaked";
isElement.className += "k-group";
twup.appendChild(idElement);
idElement.appendChild(isElement);

function filterByID(event) {
let sqlExp = '';
let idChkBoxes = document.querySelectorAll(`.id-item`);
idChkBoxes.forEach(function (node) {
if (node.checked) {
sqlExp += "'" + node.getAttribute("data-id") + "' ";
}
});
sqlExp = sqlExp.replace(/' /g, "', ");
sqlExp = sqlExp.substring(0, sqlExp.length - 2);
console.info(sqlExp);

eqLayerView.filter = {
where: "id IN (" + sqlExp + ")"
};
}
});
</script>
</head>

<body>
<div id="viewDiv"></div>

<div class="contn">
<div>
<div>
<div id="Shakemaps">Shakemaps</div>
</div>
</div>
</div>

</body>

</html>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

20 Replies
RobertScheitlin__GISP
MVP Esteemed Contributor

Cam,

  It is simply a matter of building a proper SQL expression for multiple values.

"id IN ('us70008jr5','cgi988jr52')"
CamCode
New Contributor III

Thanks so much Robert, was pursuing this until noticed this service is now gone since today? https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/USGS_Seismic_Data_v1/FeatureServe...  (no layers found) - It was working yesterday, is this just maintenance or it being marked as depreciated as well?

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Sorry I don't know. My guess is some issue or maintenance though.

0 Kudos
CamCode
New Contributor III

It is back now, strange....

0 Kudos
CamCode
New Contributor III

Is it possible to update or add to and already declared definition expression? For instance, in your format above I can declare multiple in the initial definationExpression with id, but as soon as I try to update or add to it, it never reads.

I am able to hardcode the values in now initially, or pass initial variables in with multiple taking effect now - but as soon as I try to update or change my initial i.e. my 'layer.definitionExpression = "id IN ('"+ selectedID + "','us6000a4yi')";' - it does not update, only seemingly executing the first instance of definitionExpression with the id.

It appears now I'm struggling with how to update a definitionExpression (add to, remove, or replace) - I have tried layer.refresh(); in attempt for it to read my latest definition, but still didn't seem to work, I have also tried nesting them in variables and functions. This appears to be similar to what I'm trying to do: How to setDefinitionExpression on FeatureLayer in web map? (v3.30)  -except in 3.30 version, I also tried this and wont take the syntax in 4.xx.

    let selectedID;    let datA;         layer.definitionExpression = "id IN ('')";         function filterByID(event) {        console.log('filter hit');        selectedID = event.target.getAttribute("data-id");        console.log(selectedID);        layer.refresh();        layer.definitionExpression = "id IN ('"+ selectedID +"')";    }
0 Kudos
CamCode
New Contributor III

i.e. a simple demo logic, where I can't seem to update a definationExpression (add to, remove, re-add as a new), starting with none, here I try to simple add one, console log is fine, just wont seem to take a second instant of. You can see my attempt to refresh() and "" in attempt to add a new.

    let selectedID;    let datA;         layer.definitionExpression = "id IN ('')"; <-------- initial state nothing         function filterByID(event) {        console.log('filter hit');        selectedID = event.target.getAttribute("data-id");        console.log(selectedID);        layer.refresh();        layer.definitionExpression = "id IN ('"+ selectedID +"')";  <------- attempt to update/replace with selected id     }
0 Kudos
KenBuja
MVP Honored Contributor

You have a typo on your last line. It's "definitionExpression", not "DefinitionExpression"

0 Kudos
CamCode
New Contributor III

Thanks, yeah late night typo.. I have edited the above, even with the above corrected the current dilemma persists. Here the question seems clearer: arcgis javascript api - Updating/add to definition expression - Geographic Information Systems Stack... 

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Cam,

   Sounds like you are missing the basic logic that you need to be applying. So right now you have the filterById function firing when a checkbox is checked/unchecked. Your main issue is that you are not trying to see if an other checkboxes are checked/unchecked. Each time a checkbox is checked you need to be looping through all the check boxes to see which are checked and which are not. That way you can be building your SQL statement properly.

        function filterByID(event) {
let sqlExp = '';
let idChkBoxes = document.querySelectorAll(`.id-item`);
idChkBoxes.forEach(function(node){
if(node.checked){
sqlExp += "'" + node.getAttribute("data-id") + "' ";
}
});
sqlExp = sqlExp.replace(/' /g, "', ");
sqlExp = sqlExp.substring(0, sqlExp.length - 2);
console.info(sqlExp);
eqLayerView.filter = {
where: "id IN (" + sqlExp + ")"
};
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos