Select to view content in your preferred language

FindTask/FindParameters with layerDefinition

4283
8
Jump to solution
07-30-2015 09:09 AM
TracySchloss
Frequent Contributor

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. 

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

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;
          }
        });

View solution in original post

0 Kudos
8 Replies
RobertScheitlin__GISP
MVP Emeritus

Tracy,

   Can you share more of your code for this?

0 Kudos
TracySchloss
Frequent Contributor

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>
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Tracy,

  All you have to do is set the

params.layerDefinitions = [];

when you create the new FindParameters.

0 Kudos
TracySchloss
Frequent Contributor

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[]> layerDefinitions

Array 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:%'";
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

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.

0 Kudos
TracySchloss
Frequent Contributor

By setting the layerDefinitions to an empty array, I don't see how I'm limiting anything.  

Here's my link:

Auto Complete Find Example

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.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

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;
          }
        });
0 Kudos
TracySchloss
Frequent Contributor

Clear as mud from the documentation, but now it works, thanks!

0 Kudos