AnsweredAssumed Answered

Ops dashboard -  custom table widget with search box - dataSourceProxy.executeQuery adds objectIds to http request, why?

Question asked by krystiand on Nov 9, 2015

Hi all,

I am trying to build a custom widget for ops dashboard,  based on an example table widget (Link to the sample I am using as a base: dashboard-samples/tableWidget at master · Esri/dashboard-samples · GitHub ).

 

One functionality that I am looking to add is a search/ filter box that would  users to filter rows displayed in the table. Once  a user types in a word, only the rows where selected columns(selected in configuration panel)  contain that word would be displayed, Here is the javascript for the widget:

 

define([

  "dojo/_base/declare",

  "dojo/_base/lang",

  "dijit/_WidgetBase",

  "dijit/_TemplatedMixin",

  "esri/opsdashboard/WidgetProxy",

  "dojo/store/Memory",

  "dojo/store/Observable",

  "esri/tasks/query",

  "dgrid/OnDemandGrid",

  "dojo/text!./TableWidgetTemplate.html",

  "dojo/on",

  "dojo/parser",

  "dijit/form/TextBox"

], function (declare, lang, _WidgetBase, _TemplatedMixin, WidgetProxy, Memory, Observable, Query, Grid, templateString, on) {

 

 

  return declare("TableWidget", [_WidgetBase, _TemplatedMixin, WidgetProxy], {

    templateString: templateString,

    debugName: "TableWidget",

    filterDebounce: null,

    hostReady: function () {

 

 

      // Create the store we will use to display the features in the grid

      this.store = new Observable(new Memory());

 

 

      // Get from the data source and the associated data source config

      // The dataSourceConfig stores the fields selected by the operation view publisher during configuration

      var dataSourceProxy = this.dataSourceProxies[0];

      var dataSourceConfig = this.getDataSourceConfig(dataSourceProxy);

 

 

      // Create the grid

      var columns = [];

      dataSourceConfig.selectedFieldsNames.forEach(function (field) {

        columns.push({field: field});

      });

      this.grid = new Grid({

        store: this.store,

        cleanEmptyObservers: false,

        columns: columns

      }, this.gridDiv);

 

 

      this.grid.startup();

 

 

      // Create the query object

      var fieldsToQuery = dataSourceConfig.selectedFieldsNames.slice();

      if (fieldsToQuery.indexOf(dataSourceProxy.objectIdFieldName) === -1)

        fieldsToQuery.push(dataSourceProxy.objectIdFieldName);

 

 

      this.query = new Query();

      this.query.outFields = fieldsToQuery;

      this.query.returnGeometry = false;

 

 

      on(this.filterBox, "keyup", lang.hitch(this, function() {

        if(this.filterDebounce)

          clearTimeout(this.filterDebounce);

 

 

        this.filterDebounce = setTimeout(lang.hitch(this, function(){

            var newValue = this.filterBox.value;

            var selectedIds = this.query.objectIds;

            if(this.query)

              delete this.query

 

 

            this.query = new Query();

            this.query.outFields = fieldsToQuery;

            this.query.returnGeometry = false;

 

 

            if(newValue)

            {

              var fieldsToFilter = dataSourceConfig.filterFieldsNames.slice();

              this.query.where = fieldsToFilter.map(function(elem) {

                return elem + " LIKE '%" + newValue +"%'";

              }).join(" OR ");

            }

            else

            {

              this.query.where ="1=1"

            }

            dataSourceProxy.clearSelection();

            dataSourceProxy.executeQuery(this.query).then(lang.hitch(this, function (featureSet) {

 

 

              // Show the name of the data source and the number of features returned from the query

 

 

              // Show the features in the table

              this.updateAttributeTable(featureSet, dataSourceProxy);

            }));

 

 

        }), 1000);

        }

      ));

 

 

    },

 

 

    dataSourceExpired: function (dataSourceProxy, dataSourceConfig) {

 

 

      // Execute the query. A request will be sent to the server to query for the features.

      // The results are in the featureSet

      dataSourceProxy.executeQuery(this.query).then(lang.hitch(this, function (featureSet) {

 

 

        // Show the name of the data source and the number of features returned from the query

        this.updateDataSourceInfoLabel(dataSourceProxy.name, featureSet);

 

 

        // Show the features in the table

        this.updateAttributeTable(featureSet, dataSourceProxy);

      }));

    },

 

 

    updateDataSourceInfoLabel: function (dataSourceName, featureSet) {

 

 

      // Compose the correct string to display

      var dataSourceInfo = dataSourceName;

      var featureCount = featureSet.features.length;

      if (featureCount === 0)

        dataSourceInfo += " has no feature";

      else

        dataSourceInfo += " has " + featureCount + " features";

 

 

      this.infoLabel.innerHTML = dataSourceInfo;

    },

 

 

    updateAttributeTable: function (featureSet, dataSourceProxy) {

      // For each feature put them in the store and overwrite any existing

      // Potential improvement: Remove from the store the features that were not part of this update.

      this.store.setData([]);

      this.grid.refresh();

      featureSet.features.forEach(lang.hitch(this, function (feature) {

        this.store.put(feature.attributes, {overwrite: true, id: feature.attributes[dataSourceProxy.objectIdFieldName]});

      }));

    }

  });

});

 

So I attach a keyup event to the search input and once the user is done typing I attempt to retrieve features based on the criteria, using dataSourceProxy to execute query. The problem is that I don't get all the features that I expect, only a small subset(10 out of 30). I used fiddler to investigate the raw http request and it seems that  executeQuery function of  dataSourceProxy appends objectIds parameter to that request even though objectIds of Query instance that I submit is null.

 

One thing that I believe is important to mention is that the first request that populates the table before the user can apply any filters does reach the limit of 1000 features. I have not implemented paging yet. So my theory is that all the consecutive queries include the id' that were retrieved in the first request. Is that possible? Or is there some other explanation?

 

I would appreciate any help. The documentation is not clear on the subject and the esri  js libraries included in ops dashboard are minimized so I cannot  really debug it.

Outcomes