destroy featureTable

6131
10
04-28-2016 07:37 AM
RichardMoussopo
Occasional Contributor III

There is only one method on the FeatureTable widget (startup). is there anyway to completely destroy the featureTable and recreate it each time the selection query changes.

I could create my own table to display selection query result but I would prefer using featureTable widget because of the editing capability to it.

0 Kudos
10 Replies
EvelynHernandez
Occasional Contributor III

Why u just dont show it at startup (hide it with css) and then when u make a selection u show the table with the selected data making a query with geometry?

And if the user click on something else that is not the map or the table itself u hide it again?

0 Kudos
RichardMoussopo
Occasional Contributor III

that is exactly the logic I am going to use now but the only issue is that the table is not refreshing at all. I am using myFeatureTable.grid.refresh(); but nothing happens the table keeps the same result set from the first query.

0 Kudos
EvelynHernandez
Occasional Contributor III

Maybe if u show ur code in jsfiddle we can see what is going wrong.

But remember that u need to do the query every time when u select a new item (or when u change ur map extent), so u will have to make a listener that allows to perform the query every time u make a selection or change the map extent.

For example, in my case i had to make a table that refreshes the result every time i change the map extent, so i applied a listener on the map, like:

map.on('extent-change', ()=>{   getInfoByExtent((map.extent), (myresultcallback)=>{do something with the callback that i got } });

My query is:

function getInfoByExtent(extent, callback){

var qTask = new esri.tasks.QueryTask(mylayer);

  var q= new esri.tasks.Query();

  q.where = "1=1";

  q.returnGeometry = true;

  q.outFields=["*"];

  q.geometry = extent;

  q.spatialRelationship = esri.tasks.Query.SPATIAL_REL_CONTAINS;

  qTask.execute(q, (featureSet)=>{

    callback(featureSet.features);

  }, (Errorq)=>{

    console.log(Errorq,"Error doing query by extent");

      return 0;

  });

}

0 Kudos
RichardMoussopo
Occasional Contributor III

here is the sample code. I am expecting it to work a bit more like the FeatureTable from ArcGIS Online:

<!DOCTYPE html>

<html>

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>

  <title>FeatureTable Formatting</title>

  <link rel="stylesheet" href="https://community.esri.com//js.arcgis.com/3.16/dijit/themes/claro/claro.css">

  <link rel="stylesheet" href="https://community.esri.com//js.arcgis.com/3.16/esri/css/esri.css">

  <script src="//js.arcgis.com/3.16/"></script>

  <style>

    html, body, #map {

      width: 100%;

      height: 100%;

      margin: 0;

      padding: 0;

    }

  </style>

  <script>

    // Sample from http://developers.arcgis.com/javascript/sandbox/sandbox.html?sample=featuretable_formatting  

   // Globals

    var map, myFeatureLayer, myFeatureTable;

   

    require([

      "esri/layers/FeatureLayer",

      "esri/dijit/FeatureTable",

      "esri/tasks/query",

      "esri/tasks/QueryTask",

      "esri/geometry/Extent",

      "esri/symbols/SimpleMarkerSymbol",

      "esri/symbols/SimpleLineSymbol",

      "esri/Color",

      "esri/map",

      "dojo/dom-construct",

      "dojo/dom",

      "dojo/number",

      "dojo/parser",

      "dojo/ready",

      "dojo/on",

      "dojo/_base/lang",

      "dijit/registry",

      "dijit/form/Button",

      "dijit/layout/ContentPane",

      "dijit/layout/BorderContainer",

      "dijit/form/TextBox"

    ], function (

      FeatureLayer, FeatureTable,Query, QueryTask, Extent, SimpleMarkerSymbol, SimpleLineSymbol, Color, Map,

      domConstruct, dom, dojoNum, parser, ready, on,lang,

      registry, Button, ContentPane, BorderContainer, TextBox

    ) {

      parser.parse();

      ready(function(){

        map = new Map("map",{

          basemap: "dark-gray",

          extent: new Extent({xmax: -13035353.854156237, xmin: -13053431.211345658,

            ymax: 4038351.1313028745, ymin: 4034089.766975982,

            "spatialReference":{"wkid":102100,"latestWkid":3857}

          })

        });

       

          var myFeatureLayer = new FeatureLayer("http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Redlands_Emergency_Facilities/Featu...",{

            mode: FeatureLayer.MODE_ONDEMAND,

            outFields: ["*"],

            visible: true,

            id: "fLayer"

          });

          //set a selection symbol for the featurelayer.

          var selectionSymbol =  new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_SQUARE, 12,

            new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([0, 255, 197, 1])));

          myFeatureLayer.setSelectionSymbol(selectionSymbol);

          map.addLayer(myFeatureLayer);

        map.on("load", loadTable);

       

        map.on("extent-change", updateTableByExtent);

       

        function updateTableByExtent(ext){

         

          console.log("Map Extent: ", ext.extent);

         

          var qTask = new QueryTask(myFeatureLayer);

          var q= new Query();

          q.where = "1=1";

          q.returnGeometry = true;

          q.outFields=["*"];

          q.geometry = ext.extent;

          q.spatialRelationship = Query.SPATIAL_REL_CONTAINS;

         

          qTask.execute(q, successCallBack, errorCallBack);

         

          function successCallBack(result){

            // Update the featureTable here ====> this should work more like the featureTable widget on ArcGIS Online

            console.log(result);

          }

         

          function errorCallBack(err){

           

            console.log("Ooops Error: ", err);

           

          }

        }

        function loadTable(){

          //create new FeatureTable and set its properties

          myFeatureTable = new FeatureTable({

            featureLayer : myFeatureLayer,

            map : map,

            gridOptions: {

              allowSelectAll: true,

              allowTextSelection: true,

            },

            editable: true,

            //zoomToSelection: false, //disable pan/zoom action on the map for selected features

            // showGridHeader: false,

            // showGridMenu: false,

            dateOptions: {

              //set date options at the feature table level

              //all date fields will adhere this

              datePattern: "EEEE, MMMM d, y"

            },

            //define order and visibility of fields. If the fields are not listed in 'outFIelds'

            // then they will be hidden when the table starts.

            outFields: ["factype", "facname", "organiz", "capacity", "curcapacity", "hoursoper",

                "daysoper", "opsstatus", "opendate", "imageurl", "pocname", "pocphone"

            ],

            fieldInfos: [

              {

                name: 'factype',

                alias: 'Facility Type',

              },

              {

                name: 'hoursoper',

                alias: 'Open Hours',

              },

              {

                name: 'curcapacity',

                 format: {

                  template: "${value} people"

                }

              },

              {

                name: 'daysoper',

                alias: 'Open Days',

              },

              {

                name: 'opsstatus',

                alias: 'Status',

              },

              {

                name: 'lastupdate',

                alias: 'Last Update',

                //this will override FeatureTable.dateOptions

                //settings

                dateOptions: {

                  datePattern: 'M/d/y',

                }

              },

              {

                name: 'imageurl',

                alias: 'More Info',

                editable: false

              },

              {

                name: 'pocphone',

                alias: 'Phone #',

                format: {

                  template: "tel: ${value}"

                }

              }

            ],

          }, 'myTableNode');

          myFeatureTable.startup();

        }

      });

    });

  </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>

    </div>

    <div id="bot" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom', splitter:true" style="height:50%">

      <div id="myTableNode"></div>

    </div>

  </div>

</body>

</html>

 
   
 
 
   
 
0 Kudos
JonathanUihlein
Esri Regular Contributor

Hi Richard,

I've updated some code in your sample and it should work as expected:

  // use a url string, not a layer object reference
  var qTask = new QueryTask("http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Redlands_Emergency_Facilities/Featu...");
//... 
//...
function successCallBack(result){
  if (myFeatureTable && myFeatureTable.dataStore) {
    // requires "dojo/_base/array" 
    var newData = array.map(result.features, function(feature) {
      return feature.attributes;
    });
    myFeatureTable.dataStore.data = newData;
    // The following 2 lines are a way to get the header counts to refresh as expected..
    // .. FeatureTable should probably handle this internally when dataStore is updated (potential 3.17 update)
    myFeatureTable.featureCount = newData.length;
    myFeatureTable.clearSelection();
    myFeatureTable.refresh();
  }
}

Let me know if you run into any issues with the above.

0 Kudos
JeffJacobson
Occasional Contributor III

Richard Moussopo​, you are correct when you state that the FeatureTable does not update when you update your FeatureLayer. I contacted Esri customer support in February about this and was told to use the workaround that you are trying, to destroy and recreate the table each time the feature layer is updated.

I asked them to create an enhancement request to keep the features in sync, which they did:

#ENH-000094524  [Enhancement] Update Featuretable when the underlying Featurelayer's definition query changes

Below is the function I used to create the table, which will destroy the previous table each time it is called.

var table;
function createTable() {
    // Destroy existing table.
    if (table) {
        table.destroyRecursive();
        registry.byId("tablePane").domNode.innerHTML = '<div id="table"></div>';
    }

    /**
     * Resizes the table panel as the table is collapsed or expanded.
     * @param {Event} e - Table close button click event.
     */
    function resizeTablePanel(e) {
        var gridHeaderNode = registry.byId(table._gridHeaderNode || table._gridMenu).domNode;
        var tableNode = registry.byId("tablePane").domNode;
        var borderContainer = registry.byId("borderContainer");
        var isOpening = e.target.classList.contains("toggleClosed");
        if (isOpening) {
            tableNode.style.height = tableNode.dataset.openHeight || "50%";
        } else {
            // Store the old height.
            tableNode.dataset.openHeight = tableNode.style.height || [tableNode.clientHeight, "px"].join("");
            // Set to "closed" height.
            tableNode.style.height = [gridHeaderNode.clientHeight, "px"].join("");
        }
        borderContainer.resize();
    }

    // Create the feature table
    table = new FeatureTable({
        featureLayer: layer,
        outFields: outFields,
        editable: false,
        syncSelection: false,
        zoomToSelection: false,
        // These fields are hidden by default, but user can turn them back on.
        hiddenFields: [
            "Direction_Ind",
            "RouteID",
            "Begin_ARM",
            "End_ARM",
            "SRMP_Begin_AB_Ind",
            "SRMP_End_AB_Ind",
            "SRMP_Date",
            "LRSDATE",
            "RelRouteType",
            "RelRouteQual",
            "Mid_Arm",
            "Mid_Mile_Post",
            "Project_List",
            "LOC_ERROR"
        ],
        showGridHeader: true,
        map: map
    }, "table");
    table.startup();

    // 3.15 event handler setup.

    /**
     *
     * @param {DGridRow[]} rows - The rows that were selected
     */
    table.on("dgrid-select", function (rows) {
        selectOrDeselectFeatures(rows);
    });

    /**
     *
     * @param {DGridRow[]} rows - The rows that were unselected
     */
    table.on("dgrid-deselect", function (rows) {
        selectOrDeselectFeatures(rows, true);
    });

    // 3.16 event handler setup

    /////**
    //// *
    //// * @param {DGridRow[]} rows - The rows that were selected
    //// */
    ////table.on("row-select", function (rows) {
    ////    selectOrDeselectFeatures(rows);
    ////});

    /////**
    //// *
    //// * @param {DGridRow[]} rows - The rows that were unselected
    //// */
    ////table.on("row-deselect", function (rows) {
    ////    selectOrDeselectFeatures(rows, true);
    ////});


    // resize panel when table close is toggled.
    table.tableCloseButton.addEventListener("click", resizeTablePanel);
}
RichardMoussopo
Occasional Contributor III

Thank you Jeff  for this trick. it works good.

Now the only issue I have is that the table is loading all attributes from the FeatureLayer. I only want the table to load only the selected features in the featureLayer. I have the fLayer added to the map with MODE ONDEMAND. I tried flayer.setDefinitionExpression(whereClause) it works ok but limit the records set for the next query.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Richard,

  The FeatureTable does not respect the records available based on the FeatureLayers Mode (i.e. onDemand or Selection) but I provided some code to work around that in this thread:

Can a FeatureTable only display the FeatureLayer's selection when the FeatureLayer is in MODE_SELECT...

0 Kudos
LauraMiles1
Occasional Contributor III

myFeatureTable.grid.refresh(); is still not functioning in 3.17, but I was able to use your solution Jeff.

0 Kudos