I have a featureLayer that may have a definition expression, controlled by a list of provider types. I am using Typeahead to create a list of values for the user to select from using the values from my provider field, which executes a find.
Since there might be a filter already applied, I'd like to limit the choices in my list of values to only those that meet my current definition expression on my layer. It looks like layerDefinitions on my findParameters ought to allow me to use the same expression as I have already on my featureLayer.
My findtask and parameters are defined as:
app.findTask = new FindTask(config.findFeatureLayerUrl); app.findParams = new FindParameters(); app.findParams.returnGeometry = true; app.findParams.outSpatialReference = app.spatialReference; app.findParams.layerIds = [0]; app.findParams.searchFields = ['NA_PROVIDER'];
The layer I'm searching on is layer 0. I may or may not have a definition expression set. I want the list that typeahead is producing to be limited to only those that meet the current definition. The definition is dynamic, so I can just add it when I'm defining it initially.
I've tried this:
query(node).typeahead({ minLength:4, items:10, source: function(q, process) { app.findParams.searchText = q; var def = app.featureLayer.getDefinitionExpression(); if (def) { app.findParams.layerDefinitions[0] = def;// error occurs here } app.findTask.execute(app.findParams).then(function(x) { results = x; process(x.map(function(a) { return a.value; })); }); }
I get an Uncaught TypeError: cannot set property '0' of null when attempting to the layerDefinitions. Either I don't have the right syntax for that, my definitionExpression from the featureLayer is too complicated (it is a where clause with several AND and ORs in it) or I can't set my layerDefinitions at this point in the code.
I couldn't find any threads for findParameters and layerDefinitions, which tells me it isn't used much.
Solved! Go to Solution.
Tracy,
Sorry I should have been more specific. You need to initially set the layerDefinitions to an empty arrya nd then use your code as before to set the layerDefinition.
query(node).typeahead({ minLength: 4, items: 10, source: function (q, process) { params.searchText = q; var def = featureLayer.getDefinitionExpression(); if (def) { params.layerDefinitions[0] = def; //this is the line that errors } findTask.execute(params).then(function(x) { results = x; process(x.map(function (a) { return a.value; })); }); }, updater: function (x) { var geom = asGeom(findResult(results, x)); var feat = asFeatures(findResult(results, x)); centerZoom(map, geom); map.infoWindow.setTitle('Find Provider Result'); map.infoWindow.setContent(setInfoContent(feat[0])); map.infoWindow.show(geom[0]); return x; } });
Tracy,
Can you share more of your code for this?
I think still illustrates my problem:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Auto Complete Find Example</title> <link rel="stylesheet" href="https://community.esri.com//js.arcgis.com/3.11/esri/css/esri.css"> <link rel="stylesheet" href="https://community.esri.com//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> <!-- Example found at http://odoe.net/blog/dojo-bootstrap-with-arcgis-javascript-api/ I made my example 4/29/2015 Tracy Schloss --> <style type="text/css"> #map { height: 800px; } #autocomplete { position: fixed; z-index: 99; left: 75px; top: 20px; background-color: #fff; padding: 10px; border: 1px solid #e3e3e3; } #btnClear{ padding: 4px; position:relative; top: 0px; } </style> <script type="text/javascript"> var dojoConfig = { packages: [{ name: "bootstrap", location: "//rawgit.com/xsokev/Dojo-Bootstrap/master" }] }; </script> <script src="http://js.arcgis.com/3.11/"></script> </head> <body> <script type=text/javascript> require([ 'esri/map','esri/InfoTemplate', 'dojo/query','dojo/on','dojo/dom', 'bootstrap/Typeahead', 'esri/tasks/FindParameters', 'esri/tasks/FindTask', 'esri/layers/FeatureLayer', 'esri/graphicsUtils', 'dojo/domReady!' ], function( Map, InfoTemplate, query, on, dom, Typeahead, FindParameters, FindTask, FeatureLayer, graphicsUtils ) { var pathName = "https://ogitest.oa.mo.gov"; // var url = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer'; var url = pathName + '/arcgis/rest/services/DSS/medProvider/MapServer'; var graphicsExtent = graphicsUtils.graphicsExtent; var whereClause = "(ID_PROV_TYPE_FK = '10' AND ID_SPECIALTY_FK = '80') OR (ID_PROV_TYPE_FK = '10' AND ID_SPECIALTY_FK = 'VC') OR (ID_PROV_TYPE_FK = '11' AND ID_SPECIALTY_FK = '80') OR (ID_PROV_TYPE_FK = '29' AND ID_SPECIALTY_FK = '50')"; var infoTemplate = new InfoTemplate("Provider Information"); infoTemplate.setContent(setInfoContent); var asFeatures = function asFeatures(data) { return [data.feature]; }; var asGeom = function asGeom(data){ return [data.feature.geometry]; } var findResult = function findResult(results, item) { return results.filter(function(x) { return x.value === item; }).shift(); }; /* var setExtent = function setExtent(map, features) { return map.setExtent(features); }; */ var centerZoom = function centerZoom(map,features){ return map.centerAndZoom(features[0], 15); } var map = new Map('map', { center: [-92.593, 38.5], zoom: 7, basemap: 'topo' }); var featureLayer = new FeatureLayer(url+"/0", { id:'featureLayer', mode: FeatureLayer.MODE_SNAPSHOT, outFields: ['*'], infoTemplate: infoTemplate }); featureLayer.setDefinitionExpression(whereClause); map.addLayer(featureLayer); map.on('load', function() { var findTask = new FindTask(url); var params = new FindParameters(); params.returnGeometry = true; params.outSpatialReference = map.spatialReference; params.layerIds = [0]; params.searchFields = ['NA_PROVIDER']; var results; var node = document.getElementById('search'); query(node).typeahead({ minLength:4, items:10, source: function(q, process) { params.searchText = q; var def = featureLayer.getDefinitionExpression(); if (def) { params.layerDefinitions[0] = def; //this is the line that errors } findTask.execute(params).then(function(x) { results = x; process(x.map(function(a) { return a.value; })); }); }, updater: function(x) { var geom = asGeom(findResult(results, x)); var feat = asFeatures(findResult(results, x)); centerZoom(map, geom); map.infoWindow.setTitle('Find Provider Result'); // map.infoWindow.setFeatures(feat); map.infoWindow.setContent(setInfoContent(feat[0])); map.infoWindow.show(geom[0]); /* setExtent( map, graphicsExtent( asFeatures(findResult(results, x)) )); */ return x; } }); }); //defines content of provider info tag function setInfoContent(graphic){ var formatString = ""; var addrTest = graphic.attributes.AD_LINE1; var addr2Test = graphic.attributes.AD_LINE2; var provCode = graphic.attributes.ID_PROV_TYPE_FK; var specCode = graphic.attributes.ID_SPECIALTY_FK; var phoneTest = phoneFormatter(graphic.attributes.PH_NUMBER); formatString = "<b>" + graphic.attributes.NA_PROVIDER + "</b>"; if (addrTest.length > 1) { formatString += "<br>" + addrTest; } if (addr2Test.length > 1) { formatString += "<br>" + addr2Test; } formatString += "<br>" + graphic.attributes.AD_CITY + ", " + graphic.attributes.AD_STATE + " " + graphic.attributes.AD_ZIP_CODE + "<br>" + phoneTest return formatString; } //used by setInfoContent and queryHandler_populateProviders function phoneFormatter(input){ var area = input.substr(0, 3); var pre = input.substr(3, 3); var suf = input.substr(6, 4); return "(" + area + ") " + pre + "-" + suf; } on (dom.byId('btnClear'), 'click' ,function () { dom.byId('search').value = ""; }); }) </script> <div id="map"> <div id="autocomplete"> <label>Search For Provider:</label><br/> <input id="search" type="text" class="span4"></input> <button id="btnClear" type="button" class="glyphicon glyphicon-remove" style="float:right; "></button> </div> <div> </div> </div> </body> </html>
Tracy,
All you have to do is set the
params.layerDefinitions = [];
when you create the new FindParameters.
I don't have an error, but it doesn't do anything either. The where clause limits providers to nursing homes that provide adult day care. That's not a long list, but I should still be able to type some combination of characters and expect to get a few choices. I thought my where clause was too restrictive, so I tried a where clause that returns all hospitals. Still, there is never anything that appears in my list.
According to the help, the syntax includes a number, which I assume is the layer id. Maybe I'm making a new array just for this?
String[]
> layerDefinitionsArray of layer definition expressions that allows you to filter the features of individual layers. Layer definitions with semicolons or colons are supported if using a map service published using ArcGIS Server 10.
Sample:
findParams.layerDefinitions[2] = "POP1999 > 75000"; //The following syntax is supported when using a map service published with ArcGIS Server 10. findParams.layerDefinitions[0] = "REQ_TIME like '07:%'";
Tracy,
The sample code you provided has a query that limits your data to 596 results and with adding the line of code I provided I do not see any results that do not zoom to an actual point on the map. So to me it seems to work. But I am not familiar with your data.
By setting the layerDefinitions to an empty array, I don't see how I'm limiting anything.
Here's my link:
In this example the where clause for definitionExpression on the featureLayer limits the features to hospitals. If I use the typeahead for something like Green I would expect to see Greene County Medical Center, but not all the other names that also come up. It's not restricting the returned values to only Hospitals.
If I specify an actual where clause
var whereClause = "(ID_PROV_TYPE_FK = '01' AND ID_SPECIALTY_FK = '80') OR (ID_PROV_TYPE_FK = '02' AND ID_SPECIALTY_FK = '80') OR (ID_PROV_TYPE_FK = '05' AND ID_SPECIALTY_FK = '80')";
and set my find parameters to it:
params.layerDefinitions = whereClause;
Then I get an error saying "Invalid "layerDefs' is specified.
Tracy,
Sorry I should have been more specific. You need to initially set the layerDefinitions to an empty arrya nd then use your code as before to set the layerDefinition.
query(node).typeahead({ minLength: 4, items: 10, source: function (q, process) { params.searchText = q; var def = featureLayer.getDefinitionExpression(); if (def) { params.layerDefinitions[0] = def; //this is the line that errors } findTask.execute(params).then(function(x) { results = x; process(x.map(function (a) { return a.value; })); }); }, updater: function (x) { var geom = asGeom(findResult(results, x)); var feat = asFeatures(findResult(results, x)); centerZoom(map, geom); map.infoWindow.setTitle('Find Provider Result'); map.infoWindow.setContent(setInfoContent(feat[0])); map.infoWindow.show(geom[0]); return x; } });
Clear as mud from the documentation, but now it works, thanks!