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

给你一囗甜甜゛ 提交于 2020-06-29 03:39:16

问题


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.

1.) i.e. the below filter (attempted logic 1) & CodePen:

.....
         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: https://gis.stackexchange.com/questions/364578/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.

ArcGIS - javascript - 4.15


回答1:


I am pretty sure I answer this question a couple of weeks ago, but I can't find my answer so maybe I just thought I did, in that case sorry about that.

Anyway, with a couple of fixes your code should work. The main issue here I think is that your query is not correct if you are going to use checkboxs. You need to use a set query like IN. I would be fine if you use radio buttons.

Here you have your example with the fixes I mention,

<!DOCTYPE html>
<html>

<head>
  <meta charset='utf-8' />
  <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
  <title>Filter features by attribute - 4.15</title>

  <link rel='stylesheet' href='https://js.arcgis.com/4.15/esri/themes/light/main.css' />
  <script src='https://js.arcgis.com/4.15/'></script>

  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 500px;
      width: 100%;
    }
  </style>
  <script>
    require([
      'esri/views/MapView',
      'esri/Map',
      'esri/layers/FeatureLayer',
      'esri/widgets/Expand'
    ], function (MapView, Map, FeatureLayer, Expand) {
      const layer = new FeatureLayer({
        url: 'https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/USGS_Seismic_Data_v1/FeatureServer/1/',
        outFields: ['*']
        , definitionExpression: 'eventTime >= CURRENT_TIMESTAMP - 30 AND grid_value > 2'
      });
      const map = new Map({
        basemap: 'gray-vector'
        , layers: [layer]
      });

      const view = new MapView({
        map: map,
        container: 'viewDiv',
        center: [-98, 40],
        zoom: 4
      });

      let eqLayerView;
      let selectedIDs = {};

      function updatedFilter() {
        const ids = [];
        for(const [key, value] of Object.entries(selectedIDs)) {
          if (value) {
            ids.push(`'${key}'`);
          }
        }
        eqLayerView.filter = {
          where: `id IN (${ids.join(',')})`
        };
        console.log(`[updateFilter] ${eqLayerView.filter.where}`);
      }

      const idElement = document.getElementById('id-filter');
      idElement.addEventListener('click', filterByID);
      function filterByID(event) {
        const chk = event.target;
        console.log(`[filterByID] ${chk.getAttribute('data-id')} ${chk.checked}`);
        selectedIDs[chk.getAttribute('data-id')] = chk.checked;
        updatedFilter();
      }

      view.whenLayerView(layer).then(function (layerView) {

        eqLayerView = layerView;
        updatedFilter();

        var query = layer.createQuery();
        query.outFields = ['id'];
        query.returnDistinctValues = true;
        query.returnGeometry = false;
        layer.queryFeatures(query).then(function (results) {
          results.features.map(function (feat) {
            let id = feat.attributes['id'];
            let opt = document.createElement('input');
            opt.type = 'checkbox';
            let label = document.createElement('label')
            label.innerHTML = id;
            opt.className = 'id-item visible-id';
            opt.setAttribute('data-id', id);

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

            selectedIDs[id] = false;
          });
        });

      });

    });
  </script>
</head>

<body>
  <div id='id-filter' class='esri-widget'>
  </div>
  <div id='viewDiv'></div>
</body>

</html>

BTW, I added some logs for you to see what I consider import info of the events.

Last thing, I use an auxiliary dictionary to keep track of the visible features to filter. Another way to do it would simply to query all the checkbox and add the id to the filter if it is checked.



来源:https://stackoverflow.com/questions/62502845/add-items-to-map-collectively-one-at-a-time-per-attribute-id

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!