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.