Feature Table Refresh

3278
5
Jump to solution
12-05-2016 07:25 AM
ChristopherJohnson1
Occasional Contributor II

I am using the JavaScript API version 3.16 and I am developing an application that loads three scale dependent feature layers on a map.  The layers are being added to the map after the data in a column in the layer is classified via the generateRendererTask.  There are feature tables associated with each layer and the appropriate feature table is visible when the corresponding feature layer is shown on the map.  I have a couple questions...

1. Thanks to the code from Robert Scheitlin, the feature table updates on zoom in.  On zoom out, it does not update accurately.  If I change the spatial relationship to "CONTAINS" it does.  Is it correct to change that parameter?

2. When the second feature layer displays, the header of the table is correct, but not the actual table results.  What method should I use?   I tried featureTable.grid.setStore, but that did not work.

<!DOCTYPE html>
<html>

<head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     <title>Feature Table Example For ESRI</title>
     <link rel="stylesheet" href="https://js.arcgis.com/3.16/dijit/themes/claro/claro.css">
     <link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/css/esri.css">
     <script src="https://js.arcgis.com/3.16/"></script>
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>

     <style>
          html, body {
               width: 100%;
               height: 100%;
               margin: 0;
               padding: 0;
          }

          #map {
               width: 100%;
               height: 500px;
               margin: 0;
               padding: 0;
          }

          #divGrid {
               position: absolute;
               left: 0px;
               top: 525px;
               background-color: white;
               z-index: 999;
               overflow: scroll;
               width: 100%;
               height: 400px;
               margin-bottom: 20px;
          }

          #citypoints {
               position: absolute;
               background-color: white;
               z-index: 999;
               overflow: scroll;
               width: 100%;
               height: 100%;
          }

          #citypolys {
               position: absolute;
               background-color: white;
               z-index: 999;
               overflow: scroll;
               width: 100%;
               height: 100%;
          }

          #tractpolys {
               position: absolute;
               background-color: white;
               z-index: 999;
               overflow: scroll;
               width: 100%;
               height: 100%;
          }

          .displaynone {
               display: none;
          }

          #divShowHideTable {
               position: absolute;
               top: 317px;
               left: 20px;
               z-index: 50;
          }

          #imgHiddenTable:hover {
               cursor: pointer;
          }

          #imgShownTable:hover {
               cursor: pointer;
          }

          /*#divGrid {
               position: absolute;
               top: 500px;
               width: 100%;
               height: 40%;
          }*/
     </style>

     <script>

          // declare variables and instantiate some
          var map, grid, fl_url, symbol, polygonSymbol, highlightSymbol, pointSymbol, outlineSymbol, line, renderer, featureLayer, loading, myFeatureTable, idx, title, content, drawingOptions, placeholdertxt, whereclause, fieldsToDisplay, selectionToolbar, val, fieldsoutputted, fieldsarray, lblgridheadertxt, citypointlayer, stateoutlinelayer, cityoutlinelayer, citypolygonlayer, tractpolygonlayer, citypointrenderer, stateoutlinerender, cityoutlinerenderer, citypolygonrenderer, tractpolygonrenderer, tb, citypointFT, citypolyFT, tractpolyFT, rfrshtbls, initld;
          var visiblelayers = [],
               symbolArray = [],
               labelArray = [],
               fieldsToSearch = [];

          var renderedField = 'pop2000';
          var DataUnavailableTxt = "Population < 50",
               oldExtent = null;

          // initialize modules and classes
          require([
               "esri/map"
               , "esri/graphic"
               , "esri/dijit/Basemap"
               , "esri/dijit/BasemapLayer"
               , "esri/dijit/BasemapGallery"
               , "esri/arcgis/utils"
               , "esri/urlUtils"
               , "esri/geometry/webMercatorUtils"
               , "esri/dijit/Search"
               , "esri/layers/FeatureLayer"
               , "esri/dijit/FeatureTable"
               , "esri/geometry/Extent"
               , "esri/geometry/Polygon"
               , "esri/symbols/SimpleFillSymbol"
               , "esri/layers/ArcGISDynamicMapServiceLayer"
               , "esri/layers/ImageParameters"
               , "esri/InfoTemplate"
               , "esri/renderers/ClassBreaksRenderer"
               , "esri/tasks/GenerateRendererParameters"
               , "esri/tasks/GenerateRendererTask"
               , "esri/tasks/ClassBreaksDefinition"
               , "esri/symbols/SimpleMarkerSymbol"
               , "esri/symbols/SimpleLineSymbol"
               , "esri/renderers/SimpleRenderer"
               , "esri/tasks/AlgorithmicColorRamp"
               , "esri/lang"
               , "dojo/_base/lang"
               , "esri/toolbars/draw"
               , "esri/geometry/Point"
               , "esri/geometry/geometryEngine"
               , "esri/dijit/Scalebar"
               , "esri/layers/LayerDrawingOptions"
               , "esri/request"
               , "dojo/dom-construct"
               , "esri/tasks/QueryTask"
               , "esri/tasks/query"
               , "esri/Color"
               , "dijit/form/Slider"
               , "dojo/dom-style"
               , "dgrid/Selection"
               , "dojo/ready"
               , "dojo/on"
               , "dojo/_base/array"
               , "dojox/gfx"
               , "esri/symbols/jsonUtils"
               , "dojo/_base/array"
               , "dojo/dom"
               , "dijit/form/Button"
               , "dojo/data/ItemFileReadStore"
               , "dijit/registry"
               , "dojo/parser"
               , "dojo/_base/declare"
               , "dijit/layout/BorderContainer"
               , "dijit/layout/ContentPane"
               , "dijit/form/TextBox"
               , "dgrid/extensions/ColumnHider"
               , "dojo/domReady!"
          ], function(
               Map
               , Graphic
               , Basemap
               , BasemapLayer
               , BasemapGallery
               , arcgisUtils
               , urlUtils
               , webMercatorUtils
               , Search
               , FeatureLayer
               , FeatureTable
               , Extent
               , Polygon
               , SimpleFillSymbol
               , ArcGISDynamicMapServiceLayer
               , ImageParameters
               , InfoTemplate
               , ClassBreaksRenderer
               , GenerateRendererParameters
               , GenerateRendererTask
               , ClassBreaksDefinition
               , SimpleMarkerSymbol
               , SimpleLineSymbol
               , SimpleRenderer
               , AlgorithmicColorRamp
               , esriLang
               , lang
               , Draw
               , Point
               , geometryEngine
               , Scalebar
               , LayerDrawingOptions
               , esriRequest
               , domConstruct
               , QueryTask
               , Query
               , Color
               , Slider
               , domStyle
               , Selection
               , ready
               , on
               , arrayUtils
               , gfx
               , jsonUtils
               , array
               , dom
               , Button
               , ItemFileReadStore
               , registry
               , parser
               , declare
               , BorderContainer
               , ContentPane
               , TextBox
               , ColumnHider
               , ready
          )
          {

               parser.parse();

               var DynamicMapServiceURL = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer";


               // define symbols
               highlightSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 3)).setColor(new Color([125, 125, 125, 0.35]));

               polygonSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));

               pointSymbol = new SimpleMarkerSymbol().setStyle(SimpleMarkerSymbol.STYLE_CIRCLE).setSize(8).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));

               outlineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 1);

               // intial map extent
               var initialExtent = new esri.geometry.Extent({
                    "xmin": -19525916.67711644,
                    "ymin": 1491562.5722065126,
                    "xmax": -2404022.3412415087,
                    "ymax": 9318714.26860648,
                    "spatialReference": {
                         "wkid": 102100
                    }
               });

               // instantiate infoTemplate
               var infotemp = new InfoTemplate();

               // define the dynamic map service layer and the image parameter attribute it uses
               var imageParameters = new ImageParameters();
               imageParameters.format = "png";

               var dynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(DynamicMapServiceURL, {
                    "opacity": 1.0,
                    "imageParameters": imageParameters
               });

               // add a map to the page
               map = new Map("map", {
                    //zoom: 4,
                    basemap: "gray",
                    extent: initialExtent
                    //,infoTemplate: infotemp
               });

               // events that fire, based on actions in the UI

               // the function below displays an error message and hides the div in which the map is drawn
               function showErr(err)
               {
                    'use strict';

                    console.log("Error Details: ", err);
               }

               on(dom.byId("imgShownTable"), "click", function(e)
               {
                    // hide the table
                    //ShowElement(e.id, 'divGrid', '', '');
                    $('#divGrid').hide();

                    // show the hidden Legend image  and hide the shown Legend image
                    $('#divShownTable').hide();
                    $('#divHiddenTable').show();
               });

               on(dom.byId("imgHiddenTable"), "click", function(e)
               {
                    // show the table
                    //ShowElement(e.id, 'divGrid', '', '');
                    $('#divGrid').show();

                    showHideGridAndLegend();

                    // hide the hidden Legend image and show the shown Legend image
                    $('#divShownTable').show();
                    $('#divHiddenTable').hide();
               });

               // set the initial visibility of the controls in the UI
               function setInitialVisibilityOfControls()
               {
                    'use strict';

                    // show buttons/controls
                    //$('#divHiddenLegend').show();

                    //$('#divHiddenOtherControls').show();

                    $('#divHiddenTable').show();

                    //$('#divDraw').show();

                    //// hide divs that contain controls
                    //$('#divLegend').hide();

                    //$('#divOtherControls').hide();

                    $('#divGrid').hide();

                    // make the controls draggable
                    //$("#divLegend").draggable({ containment: "#divMap", scroll: false });

                    //$('#divOtherControls').draggable({ containment: "#divMap", scroll: false });

                    //$('#divGrid').draggable({ containment: "#divMap", scroll: false });
               }

               // hide the mouse-over effect (infowindow and any graphics) when the cursor moves outside of the map extent
               map.on("mouse-out", function(evt)
               {
                    var loc = evt.mapPoint;
                    if (!map.extent.contains(loc))
                    {
                         map.infoWindow.hide();
                         map.graphics.clear();
                    }
               });

               // substitute the "(" and ", " in the CI values
               map.infoWindow.on("show", function()
               {
                    map.infoWindow.setContent(map.infoWindow._contentPane.innerHTML.replace(/\(|\)/g, '').replace(/, /g, ' - '));
               });

               // clear any graphics on the map when the infowindow hides/goes away
               map.infoWindow.on("hide", function()
               {
                    map.graphics.clear();
               });

               //create new FeatureTable and set its properties
               function AddGrid(lyrid, gridloc)
               {
                    'use strict';

                    var existingGrid = dijit.byId(gridloc);

                    if (existingGrid)
                    {
                         existingGrid.destroyRecursive(true);
                    }

                    if (lyrid === 3)
                    {
                         tractpolyFT = new FeatureTable({
                              "featureLayer": tractpolygonlayer,
                              "map": map,
                              "showStatistics": false,
                              "zoomToSelection": false,
                              "syncSelection": true,
                              "outFields": ["*"]
                         }, gridloc);

                         tractpolyFT.startup();

                    } else
                    {
                         if (lyrid === 0)
                         {
                              citypointFT = new FeatureTable({
                                   "featureLayer": citypointlayer,
                                   "map": map,
                                   "showStatistics": false,
                                   "zoomToSelection": false,
                                   "syncSelection": true,
                                   "outFields": ["*"]
                              }, gridloc);

                              citypointFT.startup();
                         } else
                         {
                              citypolyFT = new FeatureTable({
                                   "featureLayer": citypolygonlayer,
                                   "map": map,
                                   "showStatistics": false,
                                   "zoomToSelection": false,
                                   "syncSelection": true,
                                   "outFields": ["*"]
                              }, gridloc);

                              citypolyFT.startup();
                         }
                    }
               }

               // this is a custom function used to format fields in the feature table and popup
               formatVal = function(val)
               {
                    return val.replace(/\(|\)/g, '').replace(/, /g, ' - ');
               }

               // the 3 functions below are formatting functions, with their origins documented above them
               //http://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric?page=1&tab...
               var isNumber = function(n)
               {
                    return !isNaN(parseFloat(n)) && isFinite(n);
               };

               //http://james.padolsey.com/javascript/wordwrap-for-javascript/
               function wordwrap(str, width, brk, cut)
               {
                    'use strict';

                    brk = brk || '\n';
                    width = width || 75;
                    cut = cut || false;

                    if (!str)
                    {
                         return str;
                    }

                    var regex = '.{1,' + width + '}(\\s|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s|$)');

                    //this line will cause a JSLint error: Missing 'new' prefix when invoking a constructor (this error can be ignored)
                    return str.match(RegExp(regex, 'g')).join(brk);
               }

               function formatValues(num)
               {
                    'use strict';

                    return number.format(num, {
                         "places": 1
                    });
               }

               // this function is a modification of the one just above
               function formatValues2(num)
               {
                    'use strict';

                    return num = num.toFixed(1);
               }

               // the functions below dynamically generate a renderer and apply that
               // renderer generated by the createRenderer function above to the featureLayer and adds labels.
               // using individual functions, as trying to use a generic/parameterized one before did not work
               function applyctyptRenderer(citypointrenderer)
               {
                    'use strict';

                    citypointrenderer.defaultLabel = DataUnavailableTxt;

                    citypointrenderer.defaultSymbol = pointSymbol;

                    citypointlayer.setRenderer(citypointrenderer);

                    citypointlayer.renderer.setOpacityInfo(0.7);

                    map.addLayer(citypointlayer);
               }

               function applystoutRenderer(stateoutlinerenderer)
               {
                    'use strict';

                    stateoutlinerenderer.defaultLabel = DataUnavailableTxt;

                    stateoutlinerenderer.defaultSymbol = outlineSymbol;

                    stateoutlinelayer.setRenderer(stateoutlinerenderer);

                    map.addLayer(stateoutlinelayer);
               }

               function applyctyoutRenderer(cityoutlinerenderer)
               {
                    'use strict';

                    cityoutlinerenderer.defaultLabel = DataUnavailableTxt;

                    cityoutlinerenderer.defaultSymbol = outlineSymbol;

                    cityoutlinelayer.setRenderer(cityoutlinerenderer);

                    map.addLayer(cityoutlinelayer);
               }

               function applyctypolyRenderer(citypolygonrenderer)
               {
                    'use strict';

                    citypolygonrenderer.defaultLabel = DataUnavailableTxt;

                    citypolygonrenderer.defaultSymbol = polygonSymbol;

                    citypolygonlayer.setRenderer(citypolygonrenderer);

                    citypolygonlayer.renderer.setOpacityInfo(0.7);

                    map.addLayer(citypolygonlayer);
               }

               function applytrtpolyRenderer(tractpolygonrenderer)
               {
                    'use strict';

                    tractpolygonrenderer.defaultLabel = DataUnavailableTxt;

                    tractpolygonrenderer.defaultSymbol = polygonSymbol;

                    tractpolygonlayer.setRenderer(tractpolygonrenderer);

                    tractpolygonlayer.renderer.setOpacityInfo(0.7);

                    map.addLayer(tractpolygonlayer);
               }

               function createRenderer(lyr, field)
               {
                    'use strict';

                    var classDef = new ClassBreaksDefinition();
                    classDef.classificationField = field;
                    classDef.classificationMethod = $('#islClassifiers').val() ? $('#islClassifiers').val() : "natural-breaks";
                    classDef.breakCount = $('#islClassifiersCount').val() ? $('#islClassifiersCount').val() : 7;

                    switch (lyr)
                    {
                         case 0:
                              classDef.baseSymbol = pointSymbol;
                              break;

                         case 2:
                              classDef.baseSymbol = polygonSymbol;
                              break;

                         case 3:
                              classDef.baseSymbol = polygonSymbol;
                              break;


                         default:
                              classDef.baseSymbol = outlineSymbol;
                              break;
                    }

                    var colorRamp = new AlgorithmicColorRamp();

                    switch ($('#islColorScheme').val())
                    {
                         case 'OriginalBlue':
                              // original that we use on BRFSS
                              colorRamp.fromColor = new Color.fromHex("#F0F9E8");
                              colorRamp.toColor = new Color.fromHex("#2b8cbe");
                              break;

                         case 'Prevention':
                              // default color scheme for prevention
                              colorRamp.fromColor = new Color.fromHex("#ffffcc");
                              colorRamp.toColor = new Color.fromHex("#0c2c84");
                              break;

                         case 'UnhealthyBehaviors':
                              // default color scheme for unhealthy behaviors and healthy outcomes
                              colorRamp.fromColor = new Color.fromHex("#ffffd4");
                              colorRamp.toColor = new Color.fromHex("#8c2d04");
                              break;

                         case 'HealthyOutcomes':
                              // default color scheme for unhealthy behaviors and healthy outcomes
                              colorRamp.fromColor = new Color.fromHex("#ffffd4");
                              colorRamp.toColor = new Color.fromHex("#8c2d04");
                              break;

                         case 'Orange':
                              // another option -- orange-ish
                              colorRamp.fromColor = new Color.fromHex("#ffffe5");
                              colorRamp.toColor = new Color.fromHex("#662506");
                              break;

                         default:
                              // another option -- blue-ish
                              colorRamp.fromColor = new Color.fromHex("#ffffd9");
                              colorRamp.toColor = new Color.fromHex("#081d58");
                              break;
                    }

                    colorRamp.algorithm = "hsv";
                    classDef.colorRamp = colorRamp;

                    var params = new GenerateRendererParameters();
                    params.classificationDefinition = classDef;
                    params.where = whereclause;

                    var generateRenderer = new GenerateRendererTask(DynamicMapServiceURL + "/" + lyr);

                    // apply a different renderer, based on the layer
                    switch (lyr)
                    {
                         case 0:
                              generateRenderer.execute(params, applyctyptRenderer, showErr);
                              break;

                         case 2:
                              generateRenderer.execute(params, applyctypolyRenderer, showErr);
                              break;

                         case 3:
                              generateRenderer.execute(params, applytrtpolyRenderer, showErr);
                              break;

                         default:
                              break;
                    }
               }

               // show the attributes in a custom way
               function showCustomIW(e, lyrid)
               {
                    'use strict';

                    map.graphics.clear();
                    var graphic = e.graphic;

                    setIWTitleAndContent(lyrid);

                    map.infoWindow.setTitle(esriLang.substitute(graphic.attributes, infotemp.title));
                    map.infoWindow.setContent(esriLang.substitute(graphic.attributes, infotemp.content));

                    lyrid === '0' || lyrid === '2' ? map.infoWindow.resize(350, 250) : map.infoWindow.resize(350, 150);

                    var highlightGraphic = new Graphic(graphic.geometry, lyrid === '0' ? pointSymbol : polygonSymbol);

                    map.graphics.add(highlightGraphic);
                    map.infoWindow.show(e.screenPoint, map.getInfoWindowAnchor(e.screenPoint));
               }

               // hide the infowindow and any graphics
               function hideInfoWindow()
               {
                    'use strict';

                    map.graphics.clear();
                    map.infoWindow.hide();
               }

               // set title and content of infowindow
               function setIWTitleAndContent(layerid)
               {
                    'use strict';

                    map.infoWindow.hide();

                    title = "${areaname}";
                    content = "${*}";

                    infotemp.setTitle(title);
                    infotemp.setContent(content);
               }

               function LoadCityPointLayer()
               {
                    'use strict';

                    //#region CityPointLayer
                    // add city point layer

                    citypointlayer = new FeatureLayer(DynamicMapServiceURL + "/0", {
                         mode: FeatureLayer.MODE_ONDEMAND,
                         outFields: ["*"],
                         //infoTemplate: infotemp,
                         id: "City Point Layer",
                         minScale: 0,
                         maxScale: 4622324
                    });

                    createRenderer(0, renderedField);

                    //citypointlayer.on("click", function(evt)
                    //{
                    //     showCustomIW(evt, 0);
                    //});

                    //citypointlayer.on("mouse-over", function(evt)
                    //{
                    //     showCustomIW(evt, 0);
                    //});

                    //citypointlayer.on("mouse-out", hideInfoWindow);

                    citypointlayer.on("selection-complete", function(e)
                    {
                         var results = [];

                         arrayUtils.forEach(e.features, function(feature)
                         {
                              results.push(feature.attributes.OBJECTID);
                         });
                         citypointFT.selectedRowIds = results;
                         citypointFT._showSelectedRecords();
                         citypointFT._gridTitleNode.innerHTML = citypointlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
                    });

                    citypointlayer.on("selection-clear", function(e)
                    {
                         citypointlayer.setSelectionSymbol(null);
                         map.setExtent(map.extent);
                    });

                    AddGrid(0, "citypoints");

                    // limit the feature table to the records of the feature layer in the current map extent
                    // sort, as well
                    citypointlayer.on("load", function(evt)
                    {
                         citypointFT.grid.set('sort', [{
                              attribute: "NAME"
                         }]);

                         var extent = citypointlayer.fullExtent;

                         if (webMercatorUtils.canProject(extent, map))
                         {
                              map.on("extent-change", lang.hitch(this, function(params)
                              {
                                   // do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
                                   citypointlayer.setSelectionSymbol(null);

                                   // taken from https://community.esri.com/thread/173929
                                   var query = new Query();
                                   query.geometry = params.extent;
                                   query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
                                   citypointlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
                              }))
                         }
                    });
                    //#endregion
               }

               function LoadCityPolygonLayer()
               {
                    'use strict';

                    //#region CityPolygonLayer

                    // add city polygon layer

                    citypolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/2", {
                         mode: FeatureLayer.MODE_ONDEMAND,
                         outFields: ["*"],
                         //infoTemplate: infotemp,
                         id: "City Polygon Layer",
                         minScale: 4622324,
                         maxScale: 1155581
                    });

                    createRenderer(2, renderedField);

                    //citypolygonlayer.on("click", function(evt)
                    //{
                    //     showCustomIW(evt, 2);
                    //});

                    //citypolygonlayer.on("mouse-over", function(evt)
                    //{
                    //     showCustomIW(evt, 2);
                    //});

                    //citypolygonlayer.on("mouse-out", hideInfoWindow);

                    citypolygonlayer.on("selection-complete", function(e)
                    {
                         var results = [];

                         arrayUtils.forEach(e.features, function(feature)
                         {
                              results.push(feature.attributes.OBJECTID);
                         });
                         citypolyFT.selectedRowIds = results;
                         citypolyFT._showSelectedRecords();
                         citypolyFT._gridTitleNode.innerHTML = citypolygonlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
                    });

                    citypolygonlayer.on("selection-clear", function(e)
                    {
                         citypolygonlayer.setSelectionSymbol(null);
                         map.setExtent(map.extent);
                    });

                    AddGrid(2, "citypolys");

                    // limit the feature table to the records of the feature layer in the current map extent
                    // sort, as well
                    citypolygonlayer.on("load", function(evt)
                    {
                         citypolyFT.grid.set('sort', [{
                              attribute: "NAME"
                         }]);

                         var extent = citypolygonlayer.fullExtent;

                         if (webMercatorUtils.canProject(extent, map))
                         {
                              map.on("extent-change", lang.hitch(this, function(params)
                              {
                                   // do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
                                   citypolygonlayer.setSelectionSymbol(null);

                                   // taken from https://community.esri.com/thread/173929
                                   var query = new Query();
                                   query.geometry = params.extent;
                                   query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
                                   citypolygonlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
                              }))
                         }
                    });

                    //#endregion
               }

               function LoadTractPolygonLayer()
               {
                    'use strict';

                    //#region TractPolygonLayer

                    // add census tract polygon layer

                    tractpolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/3", {
                         mode: FeatureLayer.MODE_ONDEMAND,
                         outFields: ["*"],
                         //infoTemplate: infotemp,
                         id: "Census Tract Polygon Layer",
                         minScale: 1155581,
                         maxScale: 0
                    });

                    createRenderer(3, renderedField);

                    //tractpolygonlayer.on("click", function(evt)
                    //{
                    //     showCustomIW(evt, 3);
                    //});

                    //tractpolygonlayer.on("mouse-over", function(evt)
                    //{
                    //     showCustomIW(evt, 3);
                    //});

                    //tractpolygonlayer.on("mouse-out", hideInfoWindow);

                    tractpolygonlayer.on("selection-complete", function(e)
                    {
                         var results = [];

                         arrayUtils.forEach(e.features, function(feature)
                         {
                              results.push(feature.attributes.OBJECTID);
                         });
                         tractpolyFT.selectedRowIds = results;
                         tractpolyFT._showSelectedRecords();
                         tractpolyFT._gridTitleNode.innerHTML = tractpolygonlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
                    });

                    tractpolygonlayer.on("selection-clear", function(e)
                    {
                         tractpolygonlayer.setSelectionSymbol(null);
                         map.setExtent(map.extent);
                    });

                    AddGrid(3, "tractpolys");

                    // limit the feature table to the records of the feature layer in the current map extent
                    // sort, as well
                    tractpolygonlayer.on("load", function(evt)
                    {
                         tractpolyFT.grid.set('sort', [{
                              attribute: "plc_tract2010"
                         }]);

                         var extent = tractpolygonlayer.fullExtent;

                         if (webMercatorUtils.canProject(extent, map))
                         {
                              map.on("extent-change", lang.hitch(this, function(params)
                              {
                                   // do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
                                   tractpolygonlayer.setSelectionSymbol(null);

                                   // taken from https://community.esri.com/thread/173929
                                   var query = new Query();
                                   query.geometry = params.extent;
                                   query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
                                   tractpolygonlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
                              }))
                         }
                    });

                    //#endregion
               }

               // the function below shows/hides the appropriate feature table, based on the map scale
               function showHideGridAndLegend()
               {
                    'use strict';

                    //console.log(map.getScale());
                    switch (true)
                    {
                         case (map.getScale() >= 4622324):

                              $('#citypoints').show();
                              $('#citypolys').hide();
                              $('#tractpolys').hide();

                              // the feature table is sometimes not shown expanded when the window showing it opens
                              // a search online led me to a post that recommended re-sizing the table, after the window has been opened
                              // this is an attempt that only works occasionally, right now
                              if (citypointFT)
                              {
                                   citypointFT.grid.resize();
                              }

                              break;

                         case (map.getScale() < 4622324 && map.getScale() > 1155581):

                              $('#citypoints').hide();
                              $('#citypolys').show();
                              $('#tractpolys').hide();

                              // the feature table is sometimes not shown expanded when the window showing it opens
                              // a search online led me to a post that recommended re-sizing the table, after the window has been opened
                              // this is an attempt that only works occasionally, right now
                              if (citypolyFT)
                              {
                                   citypolyFT.grid.resize();
                              }

                              break;

                         case (map.getScale() <= 1155581):

                              $('#citypoints').hide();
                              $('#citypolys').hide();
                              $('#tractpolys').show();

                              // the feature table is sometimes not shown expanded when the window showing it opens
                              // a search online led me to a post that recommended re-sizing the table, after the window has been opened
                              // this is an attempt that only works occasionally, right now
                              if (tractpolyFT)
                              {
                                   tractpolyFT.grid.resize();
                              }

                              break;

                         default:

                              $('#citypoints').hide();
                              $('#citypolys').hide();
                              $('#tractpolys').hide();


                              break;
                    }
               }

               // the function below zooms to the map extent of the results of a query
               function getMapExtentOnZoom(result)
               {
                    'use strict';

                    // without the delays in calling the functions below, the functionality was not consistent.
                    if (result.features[0] !== 'undefined' && typeof result.features[0] !== 'undefined')
                    {
                         setTimeout(function()
                         {
                              //map.setExtent(result.features[0].geometry.getExtent().expand(1.45));
                              map.setExtent(result.features[0].geometry.getExtent(), true);
                         }, 450);
                    } else
                    {
                         setTimeout(function()
                         {
                              map.setExtent(initialExtent, true);
                         }, 450);
                    }

                    //showHideGridAndLegend();
               }

               // the function below queries the feature layer, based on if the where clause has a value or not
               // if it does not, it uses the current map extent/geometry to limit the feature layer query
               function zoomToSelection()
               {
                    'use strict';

                    var loc, idx;

                    // set the layer to use, based on the selected input controls --
                    // States for City data and City polygons for Census data
                    if ($('#islCities').val() !== 'undefined' && typeof $('#islCities').val() !== 'undefined')
                    {
                         loc = $('#islCities').val();
                         idx = 3;

                    } else
                    {
                         loc = $('#islStates').val() === '59' ? '1=1' : $('#islStates').val();
                         idx = 1;
                    }

                    if (typeof (loc) !== 'undefined' && loc.length > 1)
                    {
                         // define the field to query to get the extent to show on zoom To
                         var qryfield = loc;

                         // assigning the spatial reference here, once the map is already created
                         var qry = new Query();
                         qry.outSpatialReference = map.SpatialReference;
                         qry.returnGeometry = true;

                         if (idx === 3)
                         {
                              qry.where = "STPL_FIPS = '" + qryfield + "'";
                         } else
                         {
                              qry.where = "STATE = '" + qryfield + "'";
                         }

                         qry.where = qry.where.replace(/'/g, "QUOTE");

                         var qryTask = new QueryTask(DynamicMapServiceURL + "/" + idx);

                         qryTask.execute(qry, getMapExtentOnZoom, showErr);
                    }
               }

               // function that calls individual functions to load the layers and tables and zoom, if necessary
               function LoadLayers()
               {
                    'use strict';

                    //renderedField = $('#islMeasures option:selected').val() !== '' && typeof $('#islMeasures option:selected').val() !== 'undefined' ? $('#islMeasures option:selected').val() + "_CrudePrev" : 'BINGE_CrudePrev';
                    //CI = $('#islMeasures option:selected').val() !== '' && typeof $('#islMeasures option:selected').val() !== 'undefined' ? $('#islMeasures option:selected').val() + "_Crude95CI" : "BINGE_Crude95CI";

                    renderedField = 'pop2000';

                    LoadCityPointLayer();

                    LoadCityPolygonLayer();

                    LoadTractPolygonLayer();

                    //LoadStateOutlineAndCityBoundaryLayers();

                    // add drawing toolbox
                    //addDrawingTools();
               }

               // remove layers from the map
               function RemoveLayers()
               {
                    'use strict';

                    map.removeLayer(citypointlayer);
                    map.removeLayer(citypolygonlayer);
                    map.removeLayer(tractpolygonlayer);

                    //map.removeLayer(dynamicMapServiceLayer);
               }

               // load the feature layers when the map loads
               map.on("load", function()
               {

                    // add feature layers to the map and associated behaviors of feature layers

                    LoadLayers();

                    // set initil visibility of buttons/divs/etc.
                    setInitialVisibilityOfControls();
               });

               // determine which feature table to show when a user zooms
               map.on("extent-change", showHideGridAndLegend);
          });

     </script>
</head>

<body class="claro esri">
     <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width:100%; height:100%;">
          <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center', splitter:true" style="height:50%">
               <div id="map">
                    <div id="divShowHideTable">
                         <div id="divShownTable" class="displaynone">
                              <img alttext="Image that displays when the Feature Table is showing."
                                    src="Shared.Images.table_selected.png"
                                    id="imgShownTable"
                                    tooltip="Hide Table" />
                         </div>
                         <div id="divHiddenTable" class="displaynone">
                              <img alttext="Image that displays when the Feature Table is hidden."
                                    src="Shared.Images.table_default.png"
                                    id="imgHiddenTable"
                                    tooltip="Show Table" />
                         </div>
                    </div>
               </div>
          </div>
     </div>
     <div id="divGrid">
          <div id="citypoints"></div>
          <div id="citypolys"></div>
          <div id="tractpolys"></div>
     </div>
</body>
</html>

Any help is greatly appreciated.  Thanks.

- Chris

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Chris,

   OK the way I was working around the FeatureTable filtering on extent does not work in all cases (when the OIDs and table rowIDs do not coincide). So you will have to use 3.18 of the API that fixes those issues:

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Feature Table Example For ESRI</title>
    <link rel="stylesheet" href="https://js.arcgis.com/3.18/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="https://js.arcgis.com/3.18/esri/css/esri.css">
    <script src="https://js.arcgis.com/3.18/"></script>

    <style>
        html,
        body {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        #map {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        #citypoints,
        #statepolys,
        #countypolys {
            background-color: white;
            z-index: 50;
            width: 100%;
            height: 100%;
        }

        #divShowHideTable {
            position: absolute;
            top: 317px;
            left: 20px;
            z-index: 50;
        }

        #imgTable:hover {
            cursor: pointer;
        }
    </style>

    <script>
        // declare variables and instantiate some
        var map, grid, fl_url, symbol, polygonSymbol, highlightSymbol, pointSymbol, outlineSymbol, line, renderer, featureLayer, loading, myFeatureTable, idx, title, content, drawingOptions, placeholdertxt, whereclause, fieldsToDisplay,
            selectionToolbar, val, fieldsoutputted, fieldsarray, lblgridheadertxt, citypointlayer, stateoutlinelayer, cityoutlinelayer, statepolygonlayer, countypolygonlayer, citypointrenderer, stateoutlinerender, cityoutlinerenderer,
            statepolygonrenderer, countypolygonrenderer, tb, citypointFT, statepolyFT, countypolyFT, rfrshtbls, initld;
        var visiblelayers = [],
            symbolArray = [],
            labelArray = [],
            fieldsToSearch = [];

        var renderedField = 'pop2000';
        var DataUnavailableTxt = "Population < 50",
            oldExtent = null;

        // initialize modules and classes
        require([
            "esri/map", "esri/graphic", "esri/dijit/Basemap", "esri/dijit/BasemapLayer", "esri/dijit/BasemapGallery", "esri/arcgis/utils", "esri/urlUtils", "esri/geometry/webMercatorUtils", "esri/dijit/Search", "esri/layers/FeatureLayer",
            "esri/dijit/FeatureTable", "esri/geometry/Extent", "esri/geometry/Polygon", "esri/symbols/SimpleFillSymbol", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/layers/ImageParameters", "esri/InfoTemplate",
            "esri/renderers/ClassBreaksRenderer", "esri/tasks/GenerateRendererParameters", "esri/tasks/GenerateRendererTask", "esri/tasks/ClassBreaksDefinition", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
            "esri/renderers/SimpleRenderer", "esri/tasks/AlgorithmicColorRamp", "esri/lang", "dojo/_base/lang", "esri/toolbars/draw", "esri/geometry/Point", "esri/geometry/geometryEngine", "esri/dijit/Scalebar", "esri/SpatialReference",
            "esri/layers/LayerDrawingOptions", "esri/request", "dojo/dom-construct", "esri/tasks/QueryTask", "esri/tasks/query", "esri/Color", "dijit/form/Slider", "dojo/dom-style", "dgrid/Selection", "dojo/on", "esri/domUtils",
            "dojo/_base/array", "dojox/gfx", "esri/symbols/jsonUtils", "dojo/dom", "dijit/form/Button", "dojo/data/ItemFileReadStore", "dijit/registry", "dojo/parser", "dojo/_base/declare", "dijit/layout/BorderContainer",
            "dijit/layout/ContentPane", "dijit/form/TextBox", "dgrid/extensions/ColumnHider", "dojo/domReady!"
        ], function(
            Map, Graphic, Basemap, BasemapLayer, BasemapGallery, arcgisUtils, urlUtils, webMercatorUtils, Search, FeatureLayer,
            FeatureTable, Extent, Polygon, SimpleFillSymbol, ArcGISDynamicMapServiceLayer, ImageParameters, InfoTemplate,
            ClassBreaksRenderer, GenerateRendererParameters, GenerateRendererTask, ClassBreaksDefinition, SimpleMarkerSymbol, SimpleLineSymbol,
            SimpleRenderer, AlgorithmicColorRamp, esriLang, lang, Draw, Point, geometryEngine, Scalebar, SpatialReference,
            LayerDrawingOptions, esriRequest, domConstruct, QueryTask, Query, Color, Slider, domStyle, Selection, on, domUtils,
            arrayUtils, gfx, jsonUtils, dom, Button, ItemFileReadStore, registry, parser, declare, BorderContainer,
            ContentPane, TextBox, ColumnHider
        ) {

            parser.parse();
            var DynamicMapServiceURL = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer";

            // define symbols
            highlightSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 3)).setColor(new Color([125, 125, 125, 0.35]));
            polygonSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
            pointSymbol = new SimpleMarkerSymbol().setStyle(SimpleMarkerSymbol.STYLE_CIRCLE).setSize(8).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
            outlineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 1);

            // intial map extent
            var initialExtent = new esri.geometry.Extent({
                "xmin": -19525916.67711644,
                "ymin": 1491562.5722065126,
                "xmax": -2404022.3412415087,
                "ymax": 9318714.26860648,
                "spatialReference": {
                    "wkid": 102100
                }
            });

            // instantiate infoTemplate
            var infotemp = new InfoTemplate();

            // define the dynamic map service layer and the image parameter attribute it uses
            var imageParameters = new ImageParameters();
            imageParameters.format = "png";

            var dynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(DynamicMapServiceURL, {
                "opacity": 1.0,
                "imageParameters": imageParameters
            });

            // add a map to the page
            map = new Map("map", {
                basemap: "gray",
                extent: initialExtent
            });

            // events that fire, based on actions in the UI

            // the function below displays an error message and hides the div in which the map is drawn
            function showErr(err) {
                console.log("Error Details: ", err);
            }

            on(dom.byId("imgTable"), "click", function(e) {
                toggle_visibility();
            });

            function toggle_visibility() {
              var appLayout = registry.byId("allContent");
              var bottPanel = registry.byId("divGrid");
              domUtils.toggle(bottPanel);
              appLayout.resize();
            }

            // set the initial visibility of the controls in the UI
            function setInitialVisibilityOfControls() {
                domUtils.show(dom.byId('divHiddenTable'));
                var appLayout = registry.byId("allContent");
                var bottPanel = registry.byId("divGrid");
                domUtils.hide(bottPanel);
                appLayout.resize();
            }

            //create new FeatureTable and set its properties
            function AddGrid(lyrid, gridloc) {
                var existingGrid = registry.byId(gridloc);

                if (existingGrid) {
                    existingGrid.destroyRecursive(true);
                }

                switch(lyrid){
                  case 0: {
                    citypointFT = new FeatureTable({
                        "featureLayer": citypointlayer,
                        "map": map,
                        "showStatistics": false,
                        "zoomToSelection": false,
                        "syncSelection": true,
                        "outFields": ["*"]
                    }, gridloc);
                    citypointFT.startup();
                    citypointFT.sort("areaname", false);
                    break;
                  }
                  case 2: {
                    statepolyFT = new FeatureTable({
                        "featureLayer": statepolygonlayer,
                        "map": map,
                        "showStatistics": false,
                        "zoomToSelection": false,
                        "syncSelection": true,
                        "outFields": ["*"]
                    }, gridloc);
                    statepolyFT.startup();
                    statepolyFT.sort("state_name", false);
                    break;
                  }
                  case 3: {
                    countypolyFT = new FeatureTable({
                        "featureLayer": countypolygonlayer,
                        "map": map,
                        "showStatistics": false,
                        "zoomToSelection": false,
                        "syncSelection": true,
                        "outFields": ["*"]
                    }, gridloc);
                    countypolyFT.startup();
                    countypolyFT.sort("areaname", false);
                    break;
                  }
                }
            }

            // the functions below dynamically generate a renderer and apply that
            // renderer generated by the createRenderer function above to the featureLayer and adds labels.
            // using individual functions, as trying to use a generic/parameterized one before did not work
            function applyctyptRenderer(citypointrenderer) {
                citypointrenderer.defaultLabel = DataUnavailableTxt;
                citypointrenderer.defaultSymbol = pointSymbol;
                citypointlayer.setRenderer(citypointrenderer);
                citypointlayer.renderer.setOpacityInfo(0.7);
                map.addLayer(citypointlayer);
            }

            function applyctypolyRenderer(statepolygonrenderer) {
                statepolygonrenderer.defaultLabel = DataUnavailableTxt;
                statepolygonrenderer.defaultSymbol = polygonSymbol;
                statepolygonlayer.setRenderer(statepolygonrenderer);
                statepolygonlayer.renderer.setOpacityInfo(0.7);
                map.addLayer(statepolygonlayer);
            }

            function applytrtpolyRenderer(countypolygonrenderer) {
                countypolygonrenderer.defaultLabel = DataUnavailableTxt;
                countypolygonrenderer.defaultSymbol = polygonSymbol;
                countypolygonlayer.setRenderer(countypolygonrenderer);
                countypolygonlayer.renderer.setOpacityInfo(0.7);
                map.addLayer(countypolygonlayer);
            }

            function createRenderer(lyr, field) {
                var classDef = new ClassBreaksDefinition();
                classDef.classificationField = field;
                classDef.classificationMethod = "natural-breaks";
                classDef.breakCount = 7;

                switch (lyr) {
                    case 0:
                        classDef.baseSymbol = pointSymbol;
                        break;
                    case 2:
                        classDef.baseSymbol = polygonSymbol;
                        break;
                    case 3:
                        classDef.baseSymbol = polygonSymbol;
                        break;
                    default:
                        classDef.baseSymbol = outlineSymbol;
                        break;
                }

                var colorRamp = new AlgorithmicColorRamp();
                colorRamp.fromColor = new Color.fromHex("#ffffd9");
                colorRamp.toColor = new Color.fromHex("#081d58");
                colorRamp.algorithm = "hsv";
                classDef.colorRamp = colorRamp;

                var params = new GenerateRendererParameters();
                params.classificationDefinition = classDef;
                params.where = whereclause;

                var generateRenderer = new GenerateRendererTask(DynamicMapServiceURL + "/" + lyr);

                // apply a different renderer, based on the layer
                switch (lyr) {
                    case 0:
                        generateRenderer.execute(params, applyctyptRenderer, showErr);
                        break;
                    case 2:
                        generateRenderer.execute(params, applyctypolyRenderer, showErr);
                        break;
                    case 3:
                        generateRenderer.execute(params, applytrtpolyRenderer, showErr);
                        break;
                    default:
                        break;
                }
            }

            function LoadCityPointLayer() {
                //#region CityPointLayer
                // add city point layer
                citypointlayer = new FeatureLayer(DynamicMapServiceURL + "/0", {
                    mode: FeatureLayer.MODE_ONDEMAND,
                    outFields: ["*"],
                    id: "City Point Layer",
                    minScale: 0,
                    maxScale: 4622324
                });
                AddGrid(0, "citypoints");
                createRenderer(0, renderedField);
                //#endregion
            }

            function LoadStatePolygonLayer() {
                //#region StatePolygonLayer
                // add state polygon layer
                statepolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/2", {
                    mode: FeatureLayer.MODE_ONDEMAND,
                    outFields: ["*"],
                    id: "State Polygon Layer",
                    minScale: 4622324,
                    maxScale: 1155581
                });

                createRenderer(2, renderedField);
                AddGrid(2, "statepolys");
                //#endregion
            }

            function Loadcountypolygonlayer() {
                //#region countypolygonlayer
                // add county polygon layer
                countypolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/3", {
                    mode: FeatureLayer.MODE_ONDEMAND,
                    outFields: ["*"],
                    id: "County Polygon Layer",
                    minScale: 1155581,
                    maxScale: 0
                });

                createRenderer(3, renderedField);
                AddGrid(3, "countypolys");
                //#endregion
            }

            // the function below shows/hides the appropriate feature table, based on the map scale
            function showHideGridAndLegend(params) {
                var query = new Query();
                if(countypolygonlayer && countypolygonlayer.visibleAtMapScale){
                  domUtils.hide(registry.byId('citypoints'));
                  domUtils.hide(registry.byId('statepolys'));
                  domUtils.show(registry.byId('countypolys'));

                  query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
                  query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
                  countypolygonlayer.queryIds(query, lang.hitch(this, function(objectIds) {
                      countypolyFT.filterRecordsByIds(objectIds);
                      //countypolyFT._showSelectedRecords();
                      //countypolyFT._gridTitleNode.innerHTML = countypolygonlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
                      countypolyFT.resize();
                  }));
                }else if(statepolygonlayer && statepolygonlayer.visibleAtMapScale){
                  domUtils.hide(registry.byId('citypoints'));
                  domUtils.show(registry.byId('statepolys'));
                  domUtils.hide(registry.byId('countypolys'));

                  query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
                  query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
                  statepolygonlayer.queryIds(query, lang.hitch(this, function(objectIds) {
                      statepolyFT.filterRecordsByIds(objectIds);
                      //statepolyFT._showSelectedRecords();
                      //statepolyFT._gridTitleNode.innerHTML = statepolygonlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
                      statepolyFT.resize();
                  }));
                }else if(citypointlayer && citypointlayer.visibleAtMapScale){
                  domUtils.show(registry.byId('citypoints'));
                  domUtils.hide(registry.byId('statepolys'));
                  domUtils.hide(registry.byId('countypolys'));

                  query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
                  query.spatialRelationship = Query.SPATIAL_REL_CONTAINS;
                  citypointlayer.queryIds(query, lang.hitch(this, function(objectIds) {
                      citypointFT.filterRecordsByIds(objectIds);
                      //citypointFT._showSelectedRecords();
                      //citypointFT._gridTitleNode.innerHTML = citypointlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
                      citypointFT.resize();
                      citypointFT.refresh();
                  }));
                }
            }

            // function that calls individual functions to load the layers and tables and zoom, if necessary
            function LoadLayers() {
                renderedField = 'pop2000';
                LoadCityPointLayer();
                LoadStatePolygonLayer();
                Loadcountypolygonlayer();
            }

            // load the feature layers when the map loads
            map.on("load", function() {
                // add feature layers to the map and associated behaviors of feature layers
                LoadLayers();

                // set initil visibility of buttons/divs/etc.
                setInitialVisibilityOfControls();
            });

            // determine which feature table to show when a user zooms
            map.on("extent-change", showHideGridAndLegend);
        });
    </script>
</head>

<body class="claro esri">
    <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width:100%; height:100%;" id="allContent">
        <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center', splitter:true" style="height:50%">
            <div id="map">
                <div id="divShowHideTable">
                    <div id="divShownTable">
                        <img alttext="Image that displays when the Feature Table is showing." src="images/SelectRelatedRecords16.png" id="imgTable" tooltip="Show/Hide Table" />
                    </div>
                </div>
            </div>
        </div>
        <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom', splitter:true" style="height:50%" id="divGrid">
            <div id="citypoints"></div>
            <div id="statepolys"></div>
            <div id="countypolys"></div>
        </div>
    </div>
</body>
</html>

View solution in original post

5 Replies
RobertScheitlin__GISP
MVP Emeritus

Chris,

   See if this is more of what you are after (I dropped jQuery and lots of code that was not needed):

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Feature Table Example For ESRI</title>
    <link rel="stylesheet" href="https://js.arcgis.com/3.16/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/css/esri.css">
    <script src="https://js.arcgis.com/3.16/"></script>

    <style>
        html,
        body {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        #map {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        #citypoints,
        #statepolys,
        #tractpolys {
            background-color: white;
            z-index: 50;
            width: 100%;
            height: 100%;
        }

        #divShowHideTable {
            position: absolute;
            top: 317px;
            left: 20px;
            z-index: 50;
        }

        #imgTable:hover {
            cursor: pointer;
        }
    </style>

    <script>
        // declare variables and instantiate some
        var map, grid, fl_url, symbol, polygonSymbol, highlightSymbol, pointSymbol, outlineSymbol, line, renderer, featureLayer, loading, myFeatureTable, idx, title, content, drawingOptions, placeholdertxt, whereclause, fieldsToDisplay,
            selectionToolbar, val, fieldsoutputted, fieldsarray, lblgridheadertxt, citypointlayer, stateoutlinelayer, cityoutlinelayer, statepolygonlayer, tractpolygonlayer, citypointrenderer, stateoutlinerender, cityoutlinerenderer,
            statepolygonrenderer, tractpolygonrenderer, tb, citypointFT, statepolyFT, tractpolyFT, rfrshtbls, initld;
        var visiblelayers = [],
            symbolArray = [],
            labelArray = [],
            fieldsToSearch = [];

        var renderedField = 'pop2000';
        var DataUnavailableTxt = "Population < 50",
            oldExtent = null;

        // initialize modules and classes
        require([
            "esri/map", "esri/graphic", "esri/dijit/Basemap", "esri/dijit/BasemapLayer", "esri/dijit/BasemapGallery", "esri/arcgis/utils", "esri/urlUtils", "esri/geometry/webMercatorUtils", "esri/dijit/Search", "esri/layers/FeatureLayer",
            "esri/dijit/FeatureTable", "esri/geometry/Extent", "esri/geometry/Polygon", "esri/symbols/SimpleFillSymbol", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/layers/ImageParameters", "esri/InfoTemplate",
            "esri/renderers/ClassBreaksRenderer", "esri/tasks/GenerateRendererParameters", "esri/tasks/GenerateRendererTask", "esri/tasks/ClassBreaksDefinition", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
            "esri/renderers/SimpleRenderer", "esri/tasks/AlgorithmicColorRamp", "esri/lang", "dojo/_base/lang", "esri/toolbars/draw", "esri/geometry/Point", "esri/geometry/geometryEngine", "esri/dijit/Scalebar",
            "esri/layers/LayerDrawingOptions", "esri/request", "dojo/dom-construct", "esri/tasks/QueryTask", "esri/tasks/query", "esri/Color", "dijit/form/Slider", "dojo/dom-style", "dgrid/Selection", "dojo/on", "esri/domUtils",
            "dojo/_base/array", "dojox/gfx", "esri/symbols/jsonUtils", "dojo/dom", "dijit/form/Button", "dojo/data/ItemFileReadStore", "dijit/registry", "dojo/parser", "dojo/_base/declare", "dijit/layout/BorderContainer",
            "dijit/layout/ContentPane", "dijit/form/TextBox", "dgrid/extensions/ColumnHider", "dojo/domReady!"
        ], function(
            Map, Graphic, Basemap, BasemapLayer, BasemapGallery, arcgisUtils, urlUtils, webMercatorUtils, Search, FeatureLayer,
            FeatureTable, Extent, Polygon, SimpleFillSymbol, ArcGISDynamicMapServiceLayer, ImageParameters, InfoTemplate,
            ClassBreaksRenderer, GenerateRendererParameters, GenerateRendererTask, ClassBreaksDefinition, SimpleMarkerSymbol, SimpleLineSymbol,
            SimpleRenderer, AlgorithmicColorRamp, esriLang, lang, Draw, Point, geometryEngine, Scalebar,
            LayerDrawingOptions, esriRequest, domConstruct, QueryTask, Query, Color, Slider, domStyle, Selection, on, domUtils,
            arrayUtils, gfx, jsonUtils, dom, Button, ItemFileReadStore, registry, parser, declare, BorderContainer,
            ContentPane, TextBox, ColumnHider
        ) {

            parser.parse();
            var DynamicMapServiceURL = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer";

            // define symbols
            highlightSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 3)).setColor(new Color([125, 125, 125, 0.35]));
            polygonSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
            pointSymbol = new SimpleMarkerSymbol().setStyle(SimpleMarkerSymbol.STYLE_CIRCLE).setSize(8).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
            outlineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 1);

            // intial map extent
            var initialExtent = new esri.geometry.Extent({
                "xmin": -19525916.67711644,
                "ymin": 1491562.5722065126,
                "xmax": -2404022.3412415087,
                "ymax": 9318714.26860648,
                "spatialReference": {
                    "wkid": 102100
                }
            });

            // instantiate infoTemplate
            var infotemp = new InfoTemplate();

            // define the dynamic map service layer and the image parameter attribute it uses
            var imageParameters = new ImageParameters();
            imageParameters.format = "png";

            var dynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(DynamicMapServiceURL, {
                "opacity": 1.0,
                "imageParameters": imageParameters
            });

            // add a map to the page
            map = new Map("map", {
                basemap: "gray",
                extent: initialExtent
            });

            // events that fire, based on actions in the UI

            // the function below displays an error message and hides the div in which the map is drawn
            function showErr(err) {
                console.log("Error Details: ", err);
            }

            on(dom.byId("imgTable"), "click", function(e) {
                toggle_visibility();
            });

            function toggle_visibility() {
              var appLayout = registry.byId("allContent");
              var bottPanel = registry.byId("divGrid");
              domUtils.toggle(bottPanel);
              appLayout.resize();
            }

            // set the initial visibility of the controls in the UI
            function setInitialVisibilityOfControls() {
                domUtils.show(dom.byId('divHiddenTable'));
                var appLayout = registry.byId("allContent");
                var bottPanel = registry.byId("divGrid");
                domUtils.hide(bottPanel);
                appLayout.resize();
            }

            // hide the mouse-over effect (infowindow and any graphics) when the cursor moves outside of the map extent
            map.on("mouse-out", function(evt) {
                var loc = evt.mapPoint;
                if (!map.extent.contains(loc)) {
                    map.infoWindow.hide();
                    if(map.graphics){
                      map.graphics.clear();
                    }
                }
            });

            // substitute the "(" and ", " in the CI values
            map.infoWindow.on("show", function() {
                map.infoWindow.setContent(map.infoWindow._contentPane.innerHTML.replace(/\(|\)/g, '').replace(/, /g, ' - '));
            });

            // clear any graphics on the map when the infowindow hides/goes away
            map.infoWindow.on("hide", function() {
                map.graphics.clear();
            });

            //create new FeatureTable and set its properties
            function AddGrid(lyrid, gridloc) {
                var existingGrid = registry.byId(gridloc);

                if (existingGrid) {
                    existingGrid.destroyRecursive(true);
                }

                switch(lyrid){
                  case 0: {
                    citypointFT = new FeatureTable({
                        "featureLayer": citypointlayer,
                        "map": map,
                        "showStatistics": false,
                        "zoomToSelection": false,
                        "syncSelection": true,
                        "outFields": ["*"]
                    }, gridloc);
                    citypointFT.startup();
                    break;
                  }
                  case 2: {
                    statepolyFT = new FeatureTable({
                        "featureLayer": statepolygonlayer,
                        "map": map,
                        "showStatistics": false,
                        "zoomToSelection": false,
                        "syncSelection": true,
                        "outFields": ["*"]
                    }, gridloc);
                    statepolyFT.startup();
                    break;
                  }
                  case 3: {
                    tractpolyFT = new FeatureTable({
                        "featureLayer": tractpolygonlayer,
                        "map": map,
                        "showStatistics": false,
                        "zoomToSelection": false,
                        "syncSelection": true,
                        "outFields": ["*"]
                    }, gridloc);
                    tractpolyFT.startup();
                    break;
                  }
                }
            }

            // this is a custom function used to format fields in the feature table and popup
            formatVal = function(val) {
                return val.replace(/\(|\)/g, '').replace(/, /g, ' - ');
            }

            // the 3 functions below are formatting functions, with their origins documented above them
            //http://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric?page=1&tab...
            var isNumber = function(n) {
                return !isNaN(parseFloat(n)) && isFinite(n);
            };

            //http://james.padolsey.com/javascript/wordwrap-for-javascript/
            function wordwrap(str, width, brk, cut) {
                brk = brk || '\n';
                width = width || 75;
                cut = cut || false;

                if (!str) {
                    return str;
                }

                var regex = '.{1,' + width + '}(\\s|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s|$)');

                //this line will cause a JSLint error: Missing 'new' prefix when invoking a constructor (this error can be ignored)
                return str.match(RegExp(regex, 'g')).join(brk);
            }

            function formatValues(num) {
                return number.format(num, {
                    "places": 1
                });
            }

            // this function is a modification of the one just above
            function formatValues2(num) {
                return num = num.toFixed(1);
            }

            // the functions below dynamically generate a renderer and apply that
            // renderer generated by the createRenderer function above to the featureLayer and adds labels.
            // using individual functions, as trying to use a generic/parameterized one before did not work
            function applyctyptRenderer(citypointrenderer) {
                citypointrenderer.defaultLabel = DataUnavailableTxt;
                citypointrenderer.defaultSymbol = pointSymbol;
                citypointlayer.setRenderer(citypointrenderer);
                citypointlayer.renderer.setOpacityInfo(0.7);
                map.addLayer(citypointlayer);
            }

            function applystoutRenderer(stateoutlinerenderer) {
                stateoutlinerenderer.defaultLabel = DataUnavailableTxt;
                stateoutlinerenderer.defaultSymbol = outlineSymbol;
                stateoutlinelayer.setRenderer(stateoutlinerenderer);
                map.addLayer(stateoutlinelayer);
            }

            function applyctyoutRenderer(cityoutlinerenderer) {
                cityoutlinerenderer.defaultLabel = DataUnavailableTxt;
                cityoutlinerenderer.defaultSymbol = outlineSymbol;
                cityoutlinelayer.setRenderer(cityoutlinerenderer);
                map.addLayer(cityoutlinelayer);
            }

            function applyctypolyRenderer(statepolygonrenderer) {
                statepolygonrenderer.defaultLabel = DataUnavailableTxt;
                statepolygonrenderer.defaultSymbol = polygonSymbol;
                statepolygonlayer.setRenderer(statepolygonrenderer);
                statepolygonlayer.renderer.setOpacityInfo(0.7);
                map.addLayer(statepolygonlayer);
            }

            function applytrtpolyRenderer(tractpolygonrenderer) {
                tractpolygonrenderer.defaultLabel = DataUnavailableTxt;
                tractpolygonrenderer.defaultSymbol = polygonSymbol;
                tractpolygonlayer.setRenderer(tractpolygonrenderer);
                tractpolygonlayer.renderer.setOpacityInfo(0.7);
                map.addLayer(tractpolygonlayer);
            }

            function createRenderer(lyr, field) {
                var classDef = new ClassBreaksDefinition();
                classDef.classificationField = field;
                classDef.classificationMethod = "natural-breaks";
                classDef.breakCount = 7;

                switch (lyr) {
                    case 0:
                        classDef.baseSymbol = pointSymbol;
                        break;
                    case 2:
                        classDef.baseSymbol = polygonSymbol;
                        break;
                    case 3:
                        classDef.baseSymbol = polygonSymbol;
                        break;
                    default:
                        classDef.baseSymbol = outlineSymbol;
                        break;
                }

                var colorRamp = new AlgorithmicColorRamp();
                colorRamp.fromColor = new Color.fromHex("#ffffd9");
                colorRamp.toColor = new Color.fromHex("#081d58");
                colorRamp.algorithm = "hsv";
                classDef.colorRamp = colorRamp;

                var params = new GenerateRendererParameters();
                params.classificationDefinition = classDef;
                params.where = whereclause;

                var generateRenderer = new GenerateRendererTask(DynamicMapServiceURL + "/" + lyr);

                // apply a different renderer, based on the layer
                switch (lyr) {
                    case 0:
                        generateRenderer.execute(params, applyctyptRenderer, showErr);
                        break;
                    case 2:
                        generateRenderer.execute(params, applyctypolyRenderer, showErr);
                        break;
                    case 3:
                        generateRenderer.execute(params, applytrtpolyRenderer, showErr);
                        break;
                    default:
                        break;
                }
            }

            // show the attributes in a custom way
            function showCustomIW(e, lyrid) {
                map.graphics.clear();
                var graphic = e.graphic;

                setIWTitleAndContent(lyrid);

                map.infoWindow.setTitle(esriLang.substitute(graphic.attributes, infotemp.title));
                map.infoWindow.setContent(esriLang.substitute(graphic.attributes, infotemp.content));

                lyrid === '0' || lyrid === '2' ? map.infoWindow.resize(350, 250) : map.infoWindow.resize(350, 150);

                var highlightGraphic = new Graphic(graphic.geometry, lyrid === '0' ? pointSymbol : polygonSymbol);

                map.graphics.add(highlightGraphic);
                map.infoWindow.show(e.screenPoint, map.getInfoWindowAnchor(e.screenPoint));
            }

            // hide the infowindow and any graphics
            function hideInfoWindow() {
                map.graphics.clear();
                map.infoWindow.hide();
            }

            // set title and content of infowindow
            function setIWTitleAndContent(layerid) {
                map.infoWindow.hide();

                title = "${areaname}";
                content = "${*}";

                infotemp.setTitle(title);
                infotemp.setContent(content);
            }

            function LoadCityPointLayer() {
                //#region CityPointLayer
                // add city point layer
                citypointlayer = new FeatureLayer(DynamicMapServiceURL + "/0", {
                    mode: FeatureLayer.MODE_ONDEMAND,
                    outFields: ["*"],
                    id: "City Point Layer",
                    minScale: 0,
                    maxScale: 4622324
                });

                createRenderer(0, renderedField);

                citypointlayer.on("selection-complete", function(e) {
                    var results = [];

                    arrayUtils.forEach(e.features, function(feature) {
                        results.push(feature.attributes[citypointlayer.objectIdField]);
                    });
                    citypointFT.selectedRowIds = results;
                    citypointFT._showSelectedRecords();
                    citypointFT._gridTitleNode.innerHTML = citypointlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
                    citypointFT.resize();
                });

                citypointlayer.on("selection-clear", function(e) {
                    citypointlayer.setSelectionSymbol(null);
                    map.setExtent(map.extent);
                });

                AddGrid(0, "citypoints");

                // limit the feature table to the records of the feature layer in the current map extent
                // sort, as well
                citypointlayer.on("load", function(evt) {
                    citypointFT.grid.set('sort', [{
                        attribute: "NAME"
                    }]);

                    var extent = citypointlayer.fullExtent;

                    if (webMercatorUtils.canProject(extent, map)) {
                        map.on("extent-change", lang.hitch(this, function(params) {
                            // do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
                            citypointlayer.setSelectionSymbol(null);

                            // taken from https://community.esri.com/thread/173929
                            var query = new Query();
                            query.geometry = params.extent;
                            query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
                            citypointlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
                        }))
                    }
                });
                //#endregion
            }

            function LoadStatePolygonLayer() {
                //#region StatePolygonLayer
                // add state polygon layer
                statepolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/2", {
                    mode: FeatureLayer.MODE_ONDEMAND,
                    outFields: ["*"],
                    id: "State Polygon Layer",
                    minScale: 4622324,
                    maxScale: 1155581
                });

                createRenderer(2, renderedField);

                statepolygonlayer.on("selection-complete", function(e) {
                    var results = [];
                    arrayUtils.forEach(e.features, function(feature) {
                        results.push(feature.attributes[statepolygonlayer.objectIdField]);
                    });
                    statepolyFT.selectedRowIds = results;
                    statepolyFT._showSelectedRecords();
                    statepolyFT._gridTitleNode.innerHTML = statepolygonlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
                    statepolyFT.resize();
                });

                statepolygonlayer.on("selection-clear", function(e) {
                    statepolygonlayer.setSelectionSymbol(null);
                    map.setExtent(map.extent);
                });

                AddGrid(2, "statepolys");

                // limit the feature table to the records of the feature layer in the current map extent
                // sort, as well
                statepolygonlayer.on("load", function(evt) {
                    statepolyFT.grid.set('sort', [{
                        attribute: "state_name"
                    }]);
                    var extent = statepolygonlayer.fullExtent;
                    if (webMercatorUtils.canProject(extent, map)) {
                        map.on("extent-change", lang.hitch(this, function(params) {
                            // do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
                            statepolygonlayer.setSelectionSymbol(null);

                            // taken from https://community.esri.com/thread/173929
                            var query = new Query();
                            query.geometry = params.extent;
                            query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
                            statepolygonlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
                        }))
                    }
                });
                //#endregion
            }

            function LoadTractPolygonLayer() {
                //#region TractPolygonLayer
                // add census tract polygon layer
                tractpolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/3", {
                    mode: FeatureLayer.MODE_ONDEMAND,
                    outFields: ["*"],
                    id: "Census Tract Polygon Layer",
                    minScale: 1155581,
                    maxScale: 0
                });

                createRenderer(3, renderedField);

                tractpolygonlayer.on("selection-complete", function(e) {
                    var results = [];

                    arrayUtils.forEach(e.features, function(feature) {
                        results.push(feature.attributes[tractpolygonlayer.objectIdField]);
                    });
                    tractpolyFT.selectedRowIds = results;
                    tractpolyFT._showSelectedRecords();
                    tractpolyFT._gridTitleNode.innerHTML = tractpolygonlayer.name + ' (' + (results.length != 'undefined' ? (results.length > 1 ? results.length + ' Features)' : 1 + ' Feature)') : "");
                    tractpolyFT.resize();
                });

                tractpolygonlayer.on("selection-clear", function(e) {
                    tractpolygonlayer.setSelectionSymbol(null);
                    map.setExtent(map.extent);
                });

                AddGrid(3, "tractpolys");

                // limit the feature table to the records of the feature layer in the current map extent
                // sort, as well
                tractpolygonlayer.on("load", function(evt) {
                    tractpolyFT.grid.set('sort', [{
                        attribute: "name"
                    }]);

                    var extent = tractpolygonlayer.fullExtent;

                    if (webMercatorUtils.canProject(extent, map)) {
                        map.on("extent-change", lang.hitch(this, function(params) {
                            // do not highlight the features when the map extent changes, as can be seen from below...it triggers a selection
                            tractpolygonlayer.setSelectionSymbol(null);

                            // taken from https://community.esri.com/thread/173929
                            var query = new Query();
                            query.geometry = params.extent;
                            query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
                            tractpolygonlayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);
                        }))
                    }
                });
                //#endregion
            }

            // the function below shows/hides the appropriate feature table, based on the map scale
            function showHideGridAndLegend() {
                //console.log(map.getScale());
                switch (true) {
                    case (map.getScale() >= 4622324):
                        domUtils.show(registry.byId('citypoints'));
                        domUtils.hide(registry.byId('statepolys'));
                        domUtils.hide(registry.byId('tractpolys'));
                        // the feature table is sometimes not shown expanded when the window showing it opens
                        // a search online led me to a post that recommended re-sizing the table, after the window has been opened
                        // this is an attempt that only works occasionally, right now
                        if (citypointFT) {
                            citypointFT.resize();
                        }
                        break;
                    case (map.getScale() < 4622324 && map.getScale() > 1155581):
                        domUtils.hide(registry.byId('citypoints'));
                        domUtils.show(registry.byId('statepolys'));
                        domUtils.hide(registry.byId('tractpolys'));
                        // the feature table is sometimes not shown expanded when the window showing it opens
                        // a search online led me to a post that recommended re-sizing the table, after the window has been opened
                        // this is an attempt that only works occasionally, right now
                        if (statepolyFT) {
                            statepolyFT.resize();
                        }
                        break;
                    case (map.getScale() <= 1155581):
                        domUtils.hide(registry.byId('citypoints'));
                        domUtils.hide(registry.byId('statepolys'));
                        domUtils.show(registry.byId('tractpolys'));
                        // the feature table is sometimes not shown expanded when the window showing it opens
                        // a search online led me to a post that recommended re-sizing the table, after the window has been opened
                        // this is an attempt that only works occasionally, right now
                        if (tractpolyFT) {
                            tractpolyFT.resize();
                        }
                        break;
                    default:
                        domUtils.hide(registry.byId('citypoints'));
                        domUtils.hide(registry.byId('statepolys'));
                        domUtils.hide(registry.byId('tractpolys'));
                        break;
                }
            }

            // the function below zooms to the map extent of the results of a query
            function getMapExtentOnZoom(result) {
                // without the delays in calling the functions below, the functionality was not consistent.
                if (result.features[0] !== 'undefined' && typeof result.features[0] !== 'undefined') {
                    setTimeout(function() {
                        //map.setExtent(result.features[0].geometry.getExtent().expand(1.45));
                        map.setExtent(result.features[0].geometry.getExtent(), true);
                    }, 450);
                } else {
                    setTimeout(function() {
                        map.setExtent(initialExtent, true);
                    }, 450);
                }
            }

            // function that calls individual functions to load the layers and tables and zoom, if necessary
            function LoadLayers() {
                renderedField = 'pop2000';
                LoadCityPointLayer();
                LoadStatePolygonLayer();
                LoadTractPolygonLayer();
            }

            // remove layers from the map
            function RemoveLayers() {
                map.removeLayer(citypointlayer);
                map.removeLayer(statepolygonlayer);
                map.removeLayer(tractpolygonlayer);
            }

            // load the feature layers when the map loads
            map.on("load", function() {
                // add feature layers to the map and associated behaviors of feature layers
                LoadLayers();

                // set initil visibility of buttons/divs/etc.
                setInitialVisibilityOfControls();
            });

            // determine which feature table to show when a user zooms
            map.on("extent-change", showHideGridAndLegend);
        });
    </script>
</head>

<body class="claro esri">
    <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width:100%; height:100%;" id="allContent">
        <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center', splitter:true" style="height:50%">
            <div id="map">
                <div id="divShowHideTable">
                    <div id="divShownTable">
                        <img alttext="Image that displays when the Feature Table is showing." src="images/SelectRelatedRecords16.png" id="imgTable" tooltip="Show/Hide Table" />
                    </div>
                </div>
            </div>
        </div>
        <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom', splitter:true" style="height:50%" id="divGrid">
            <div id="citypoints"></div>
            <div id="statepolys"></div>
            <div id="tractpolys"></div>
        </div>
    </div>
</body>
</html>
ChristopherJohnson1
Occasional Contributor II

Hi, Robert.  Thank you again VERY much for taking the time to investigate this issue.  I am still seeing a similar issue, as before.

For example, when zoomed into the Counties, the table header shows the correct number of values.  However, the table grid shows values not currently shown on the map.

As a matter of fact, even when viewing Cities and when zoomed into the MidWest, Hawaii is displayed in the table.

And again, when zooming back out from Cities, the table header count does not update correctly.

Is this normal behavior?

Thanks...Chris

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Chris,

   OK the way I was working around the FeatureTable filtering on extent does not work in all cases (when the OIDs and table rowIDs do not coincide). So you will have to use 3.18 of the API that fixes those issues:

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Feature Table Example For ESRI</title>
    <link rel="stylesheet" href="https://js.arcgis.com/3.18/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="https://js.arcgis.com/3.18/esri/css/esri.css">
    <script src="https://js.arcgis.com/3.18/"></script>

    <style>
        html,
        body {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        #map {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        #citypoints,
        #statepolys,
        #countypolys {
            background-color: white;
            z-index: 50;
            width: 100%;
            height: 100%;
        }

        #divShowHideTable {
            position: absolute;
            top: 317px;
            left: 20px;
            z-index: 50;
        }

        #imgTable:hover {
            cursor: pointer;
        }
    </style>

    <script>
        // declare variables and instantiate some
        var map, grid, fl_url, symbol, polygonSymbol, highlightSymbol, pointSymbol, outlineSymbol, line, renderer, featureLayer, loading, myFeatureTable, idx, title, content, drawingOptions, placeholdertxt, whereclause, fieldsToDisplay,
            selectionToolbar, val, fieldsoutputted, fieldsarray, lblgridheadertxt, citypointlayer, stateoutlinelayer, cityoutlinelayer, statepolygonlayer, countypolygonlayer, citypointrenderer, stateoutlinerender, cityoutlinerenderer,
            statepolygonrenderer, countypolygonrenderer, tb, citypointFT, statepolyFT, countypolyFT, rfrshtbls, initld;
        var visiblelayers = [],
            symbolArray = [],
            labelArray = [],
            fieldsToSearch = [];

        var renderedField = 'pop2000';
        var DataUnavailableTxt = "Population < 50",
            oldExtent = null;

        // initialize modules and classes
        require([
            "esri/map", "esri/graphic", "esri/dijit/Basemap", "esri/dijit/BasemapLayer", "esri/dijit/BasemapGallery", "esri/arcgis/utils", "esri/urlUtils", "esri/geometry/webMercatorUtils", "esri/dijit/Search", "esri/layers/FeatureLayer",
            "esri/dijit/FeatureTable", "esri/geometry/Extent", "esri/geometry/Polygon", "esri/symbols/SimpleFillSymbol", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/layers/ImageParameters", "esri/InfoTemplate",
            "esri/renderers/ClassBreaksRenderer", "esri/tasks/GenerateRendererParameters", "esri/tasks/GenerateRendererTask", "esri/tasks/ClassBreaksDefinition", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
            "esri/renderers/SimpleRenderer", "esri/tasks/AlgorithmicColorRamp", "esri/lang", "dojo/_base/lang", "esri/toolbars/draw", "esri/geometry/Point", "esri/geometry/geometryEngine", "esri/dijit/Scalebar", "esri/SpatialReference",
            "esri/layers/LayerDrawingOptions", "esri/request", "dojo/dom-construct", "esri/tasks/QueryTask", "esri/tasks/query", "esri/Color", "dijit/form/Slider", "dojo/dom-style", "dgrid/Selection", "dojo/on", "esri/domUtils",
            "dojo/_base/array", "dojox/gfx", "esri/symbols/jsonUtils", "dojo/dom", "dijit/form/Button", "dojo/data/ItemFileReadStore", "dijit/registry", "dojo/parser", "dojo/_base/declare", "dijit/layout/BorderContainer",
            "dijit/layout/ContentPane", "dijit/form/TextBox", "dgrid/extensions/ColumnHider", "dojo/domReady!"
        ], function(
            Map, Graphic, Basemap, BasemapLayer, BasemapGallery, arcgisUtils, urlUtils, webMercatorUtils, Search, FeatureLayer,
            FeatureTable, Extent, Polygon, SimpleFillSymbol, ArcGISDynamicMapServiceLayer, ImageParameters, InfoTemplate,
            ClassBreaksRenderer, GenerateRendererParameters, GenerateRendererTask, ClassBreaksDefinition, SimpleMarkerSymbol, SimpleLineSymbol,
            SimpleRenderer, AlgorithmicColorRamp, esriLang, lang, Draw, Point, geometryEngine, Scalebar, SpatialReference,
            LayerDrawingOptions, esriRequest, domConstruct, QueryTask, Query, Color, Slider, domStyle, Selection, on, domUtils,
            arrayUtils, gfx, jsonUtils, dom, Button, ItemFileReadStore, registry, parser, declare, BorderContainer,
            ContentPane, TextBox, ColumnHider
        ) {

            parser.parse();
            var DynamicMapServiceURL = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer";

            // define symbols
            highlightSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 3)).setColor(new Color([125, 125, 125, 0.35]));
            polygonSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_SOLID).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
            pointSymbol = new SimpleMarkerSymbol().setStyle(SimpleMarkerSymbol.STYLE_CIRCLE).setSize(8).setOutline(new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([85, 85, 85]), 1)).setColor(new Color([153, 153, 153]));
            outlineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([91, 91, 91]), 1);

            // intial map extent
            var initialExtent = new esri.geometry.Extent({
                "xmin": -19525916.67711644,
                "ymin": 1491562.5722065126,
                "xmax": -2404022.3412415087,
                "ymax": 9318714.26860648,
                "spatialReference": {
                    "wkid": 102100
                }
            });

            // instantiate infoTemplate
            var infotemp = new InfoTemplate();

            // define the dynamic map service layer and the image parameter attribute it uses
            var imageParameters = new ImageParameters();
            imageParameters.format = "png";

            var dynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(DynamicMapServiceURL, {
                "opacity": 1.0,
                "imageParameters": imageParameters
            });

            // add a map to the page
            map = new Map("map", {
                basemap: "gray",
                extent: initialExtent
            });

            // events that fire, based on actions in the UI

            // the function below displays an error message and hides the div in which the map is drawn
            function showErr(err) {
                console.log("Error Details: ", err);
            }

            on(dom.byId("imgTable"), "click", function(e) {
                toggle_visibility();
            });

            function toggle_visibility() {
              var appLayout = registry.byId("allContent");
              var bottPanel = registry.byId("divGrid");
              domUtils.toggle(bottPanel);
              appLayout.resize();
            }

            // set the initial visibility of the controls in the UI
            function setInitialVisibilityOfControls() {
                domUtils.show(dom.byId('divHiddenTable'));
                var appLayout = registry.byId("allContent");
                var bottPanel = registry.byId("divGrid");
                domUtils.hide(bottPanel);
                appLayout.resize();
            }

            //create new FeatureTable and set its properties
            function AddGrid(lyrid, gridloc) {
                var existingGrid = registry.byId(gridloc);

                if (existingGrid) {
                    existingGrid.destroyRecursive(true);
                }

                switch(lyrid){
                  case 0: {
                    citypointFT = new FeatureTable({
                        "featureLayer": citypointlayer,
                        "map": map,
                        "showStatistics": false,
                        "zoomToSelection": false,
                        "syncSelection": true,
                        "outFields": ["*"]
                    }, gridloc);
                    citypointFT.startup();
                    citypointFT.sort("areaname", false);
                    break;
                  }
                  case 2: {
                    statepolyFT = new FeatureTable({
                        "featureLayer": statepolygonlayer,
                        "map": map,
                        "showStatistics": false,
                        "zoomToSelection": false,
                        "syncSelection": true,
                        "outFields": ["*"]
                    }, gridloc);
                    statepolyFT.startup();
                    statepolyFT.sort("state_name", false);
                    break;
                  }
                  case 3: {
                    countypolyFT = new FeatureTable({
                        "featureLayer": countypolygonlayer,
                        "map": map,
                        "showStatistics": false,
                        "zoomToSelection": false,
                        "syncSelection": true,
                        "outFields": ["*"]
                    }, gridloc);
                    countypolyFT.startup();
                    countypolyFT.sort("areaname", false);
                    break;
                  }
                }
            }

            // the functions below dynamically generate a renderer and apply that
            // renderer generated by the createRenderer function above to the featureLayer and adds labels.
            // using individual functions, as trying to use a generic/parameterized one before did not work
            function applyctyptRenderer(citypointrenderer) {
                citypointrenderer.defaultLabel = DataUnavailableTxt;
                citypointrenderer.defaultSymbol = pointSymbol;
                citypointlayer.setRenderer(citypointrenderer);
                citypointlayer.renderer.setOpacityInfo(0.7);
                map.addLayer(citypointlayer);
            }

            function applyctypolyRenderer(statepolygonrenderer) {
                statepolygonrenderer.defaultLabel = DataUnavailableTxt;
                statepolygonrenderer.defaultSymbol = polygonSymbol;
                statepolygonlayer.setRenderer(statepolygonrenderer);
                statepolygonlayer.renderer.setOpacityInfo(0.7);
                map.addLayer(statepolygonlayer);
            }

            function applytrtpolyRenderer(countypolygonrenderer) {
                countypolygonrenderer.defaultLabel = DataUnavailableTxt;
                countypolygonrenderer.defaultSymbol = polygonSymbol;
                countypolygonlayer.setRenderer(countypolygonrenderer);
                countypolygonlayer.renderer.setOpacityInfo(0.7);
                map.addLayer(countypolygonlayer);
            }

            function createRenderer(lyr, field) {
                var classDef = new ClassBreaksDefinition();
                classDef.classificationField = field;
                classDef.classificationMethod = "natural-breaks";
                classDef.breakCount = 7;

                switch (lyr) {
                    case 0:
                        classDef.baseSymbol = pointSymbol;
                        break;
                    case 2:
                        classDef.baseSymbol = polygonSymbol;
                        break;
                    case 3:
                        classDef.baseSymbol = polygonSymbol;
                        break;
                    default:
                        classDef.baseSymbol = outlineSymbol;
                        break;
                }

                var colorRamp = new AlgorithmicColorRamp();
                colorRamp.fromColor = new Color.fromHex("#ffffd9");
                colorRamp.toColor = new Color.fromHex("#081d58");
                colorRamp.algorithm = "hsv";
                classDef.colorRamp = colorRamp;

                var params = new GenerateRendererParameters();
                params.classificationDefinition = classDef;
                params.where = whereclause;

                var generateRenderer = new GenerateRendererTask(DynamicMapServiceURL + "/" + lyr);

                // apply a different renderer, based on the layer
                switch (lyr) {
                    case 0:
                        generateRenderer.execute(params, applyctyptRenderer, showErr);
                        break;
                    case 2:
                        generateRenderer.execute(params, applyctypolyRenderer, showErr);
                        break;
                    case 3:
                        generateRenderer.execute(params, applytrtpolyRenderer, showErr);
                        break;
                    default:
                        break;
                }
            }

            function LoadCityPointLayer() {
                //#region CityPointLayer
                // add city point layer
                citypointlayer = new FeatureLayer(DynamicMapServiceURL + "/0", {
                    mode: FeatureLayer.MODE_ONDEMAND,
                    outFields: ["*"],
                    id: "City Point Layer",
                    minScale: 0,
                    maxScale: 4622324
                });
                AddGrid(0, "citypoints");
                createRenderer(0, renderedField);
                //#endregion
            }

            function LoadStatePolygonLayer() {
                //#region StatePolygonLayer
                // add state polygon layer
                statepolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/2", {
                    mode: FeatureLayer.MODE_ONDEMAND,
                    outFields: ["*"],
                    id: "State Polygon Layer",
                    minScale: 4622324,
                    maxScale: 1155581
                });

                createRenderer(2, renderedField);
                AddGrid(2, "statepolys");
                //#endregion
            }

            function Loadcountypolygonlayer() {
                //#region countypolygonlayer
                // add county polygon layer
                countypolygonlayer = new FeatureLayer(DynamicMapServiceURL + "/3", {
                    mode: FeatureLayer.MODE_ONDEMAND,
                    outFields: ["*"],
                    id: "County Polygon Layer",
                    minScale: 1155581,
                    maxScale: 0
                });

                createRenderer(3, renderedField);
                AddGrid(3, "countypolys");
                //#endregion
            }

            // the function below shows/hides the appropriate feature table, based on the map scale
            function showHideGridAndLegend(params) {
                var query = new Query();
                if(countypolygonlayer && countypolygonlayer.visibleAtMapScale){
                  domUtils.hide(registry.byId('citypoints'));
                  domUtils.hide(registry.byId('statepolys'));
                  domUtils.show(registry.byId('countypolys'));

                  query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
                  query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
                  countypolygonlayer.queryIds(query, lang.hitch(this, function(objectIds) {
                      countypolyFT.filterRecordsByIds(objectIds);
                      //countypolyFT._showSelectedRecords();
                      //countypolyFT._gridTitleNode.innerHTML = countypolygonlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
                      countypolyFT.resize();
                  }));
                }else if(statepolygonlayer && statepolygonlayer.visibleAtMapScale){
                  domUtils.hide(registry.byId('citypoints'));
                  domUtils.show(registry.byId('statepolys'));
                  domUtils.hide(registry.byId('countypolys'));

                  query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
                  query.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
                  statepolygonlayer.queryIds(query, lang.hitch(this, function(objectIds) {
                      statepolyFT.filterRecordsByIds(objectIds);
                      //statepolyFT._showSelectedRecords();
                      //statepolyFT._gridTitleNode.innerHTML = statepolygonlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
                      statepolyFT.resize();
                  }));
                }else if(citypointlayer && citypointlayer.visibleAtMapScale){
                  domUtils.show(registry.byId('citypoints'));
                  domUtils.hide(registry.byId('statepolys'));
                  domUtils.hide(registry.byId('countypolys'));

                  query.geometry = webMercatorUtils.project(params.extent, new SpatialReference({wkid:4326}));
                  query.spatialRelationship = Query.SPATIAL_REL_CONTAINS;
                  citypointlayer.queryIds(query, lang.hitch(this, function(objectIds) {
                      citypointFT.filterRecordsByIds(objectIds);
                      //citypointFT._showSelectedRecords();
                      //citypointFT._gridTitleNode.innerHTML = citypointlayer.name + ' (' + (objectIds.length != 'undefined' ? (objectIds.length > 1 ? objectIds.length + ' Features)' : 1 + ' Feature)') : "");
                      citypointFT.resize();
                      citypointFT.refresh();
                  }));
                }
            }

            // function that calls individual functions to load the layers and tables and zoom, if necessary
            function LoadLayers() {
                renderedField = 'pop2000';
                LoadCityPointLayer();
                LoadStatePolygonLayer();
                Loadcountypolygonlayer();
            }

            // load the feature layers when the map loads
            map.on("load", function() {
                // add feature layers to the map and associated behaviors of feature layers
                LoadLayers();

                // set initil visibility of buttons/divs/etc.
                setInitialVisibilityOfControls();
            });

            // determine which feature table to show when a user zooms
            map.on("extent-change", showHideGridAndLegend);
        });
    </script>
</head>

<body class="claro esri">
    <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width:100%; height:100%;" id="allContent">
        <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center', splitter:true" style="height:50%">
            <div id="map">
                <div id="divShowHideTable">
                    <div id="divShownTable">
                        <img alttext="Image that displays when the Feature Table is showing." src="images/SelectRelatedRecords16.png" id="imgTable" tooltip="Show/Hide Table" />
                    </div>
                </div>
            </div>
        </div>
        <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom', splitter:true" style="height:50%" id="divGrid">
            <div id="citypoints"></div>
            <div id="statepolys"></div>
            <div id="countypolys"></div>
        </div>
    </div>
</body>
</html>
ChristopherJohnson1
Occasional Contributor II

Thanks, Robert.  I will give this a try.

- Chris

0 Kudos
ChristopherJohnson1
Occasional Contributor II

Thanks again, Robert!  It looks like your solution will work for us.  We are integrating this into a custom BI tool, so the code was modified a bit.  Thanks again!

- Chris

0 Kudos