Search Results in Popup - deferred?

2209
5
Jump to solution
05-04-2016 02:56 PM
LauraMiles1
Occasional Contributor III


Hi, I'm trying to use the Search widget with the option to return multiple results (autoSelect: false). This means results won't automatically be populated into my popup, and I must handle that. The popup's setFeatures method takes a deferred. I've been trying to research what this means really but I don't quite understand. The Search widget is returning an array of results; how do I turn that into a deferred and set it as the popup's features?

I understand that creating a deferred object would reference a function. I see and understand how this works with the Identify here. But in this case, as far as I can tell no function is required to return the results? Results are returned on the Search widget's event 'search-results'. Should the Search method itself be a deferred object?

Here's my guess at how I thought it might go, which doesn't work:

var s = new Search({

            enableSearchingAll: false,

            autoSelect: false,

            map: mapObj,

            maxResults: 100,

            maxSuggestions: 100

         }, "search");

var searchDeferred = s

                 .execute()

                 .addCallback(function(e){

                     s.startup();

                 });

        

         s.on('search-results', function(e){

              console.log('search results: ', e.results);

              console.log(e.numResults);

              mapObj.infoWindow.setFeatures(searchDeferred);

              mapObj.infoWindow.show(e.mapPoint);   

         });

Trying to run the above results in Uncaught TypeError: s.execute is not a function

I have a jsfiddle here, any pointers are greatly appreciated.

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Laura,

  The deferred would have to return features and the search widget does but they are buried in the result. You do not have to provide a deferred to the map.infoWindow.setFeatures it can take an array of features as well so here is some code based on your fiddle:

<!DOCTYPE html>
<html dir="ltr">

<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>ArcGIS API for JavaScript | Basic Search</title>
   <link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/themes/calcite/dijit/calcite.css">
   <link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/themes/calcite/esri/esri.css">
   <style>
      html,
      body,
      #map {
         height: 100%;
         width: 100%;
         margin: 0;
         padding: 0;
      }
      #search {
         display: block;
         position: absolute;
         z-index: 2;
         top: 20px;
         left: 74px;
      }
   </style>
   <script src="https://js.arcgis.com/3.16/"></script>
   <script>
      require([

        "esri/map",
        "esri/dijit/Search",
        "dojo/Deferred",
        "dojo/_base/array",
        "dojo/_base/lang",
        "esri/InfoTemplate",
        "dojo/domReady!"

      ], function (Map, Search, Deferred, array, lang, InfoTemplate) {
         var map = new Map("map", {
            basemap: "gray",
            center: [-120.435, 46.159], // lon, lat
            zoom: 7
         });

         var search = new Search({
            map: map,
            autoSelect: false
         }, "search");

         search.on('search-results', function(e){
             console.log('search results', e);
  //console.info(e.results);
             var infoTemplate = new InfoTemplate("Attributes", "${*}");
             var features = array.map(e.results[0], lang.hitch(this, function(result){
               result.feature.setInfoTemplate(infoTemplate);
               return result.feature;
             }));
             map.infoWindow.setFeatures(features);
             //There is not mapPoint in the event so you need to do something else here
             map.infoWindow.show(e.mapPoint);
         });

      });
   </script>
</head>
<body class="calcite">
   <div id="search"></div>
   <div id="map"></div>
</body>

</html>

View solution in original post

5 Replies
RobertScheitlin__GISP
MVP Emeritus

Laura,

  The deferred would have to return features and the search widget does but they are buried in the result. You do not have to provide a deferred to the map.infoWindow.setFeatures it can take an array of features as well so here is some code based on your fiddle:

<!DOCTYPE html>
<html dir="ltr">

<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>ArcGIS API for JavaScript | Basic Search</title>
   <link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/themes/calcite/dijit/calcite.css">
   <link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/themes/calcite/esri/esri.css">
   <style>
      html,
      body,
      #map {
         height: 100%;
         width: 100%;
         margin: 0;
         padding: 0;
      }
      #search {
         display: block;
         position: absolute;
         z-index: 2;
         top: 20px;
         left: 74px;
      }
   </style>
   <script src="https://js.arcgis.com/3.16/"></script>
   <script>
      require([

        "esri/map",
        "esri/dijit/Search",
        "dojo/Deferred",
        "dojo/_base/array",
        "dojo/_base/lang",
        "esri/InfoTemplate",
        "dojo/domReady!"

      ], function (Map, Search, Deferred, array, lang, InfoTemplate) {
         var map = new Map("map", {
            basemap: "gray",
            center: [-120.435, 46.159], // lon, lat
            zoom: 7
         });

         var search = new Search({
            map: map,
            autoSelect: false
         }, "search");

         search.on('search-results', function(e){
             console.log('search results', e);
  //console.info(e.results);
             var infoTemplate = new InfoTemplate("Attributes", "${*}");
             var features = array.map(e.results[0], lang.hitch(this, function(result){
               result.feature.setInfoTemplate(infoTemplate);
               return result.feature;
             }));
             map.infoWindow.setFeatures(features);
             //There is not mapPoint in the event so you need to do something else here
             map.infoWindow.show(e.mapPoint);
         });

      });
   </script>
</head>
<body class="calcite">
   <div id="search"></div>
   <div id="map"></div>
</body>

</html>
LauraMiles1
Occasional Contributor III

Hi Robert,

I tried to implement this, but I'm setting some sources for the Search widget to layers in my map. It seems only the attributes for the first source set are being sent to the InfoWindow (tested by changing which source is pushed first) - searching any other sources results in the InfoWindow saying "no information available", however results are being returned in the console (ie. search the Counties and type "Washington", the console says 31 results are found and their attributes can be seen there - jsfiddle).

Also, I'm using a Locator for the address portion - it's not returning any attributes to the InfoWindow or the console other than "score". This seems odd since the attributes (ie. the full address) are popping up in the suggestion dropdown while you're typing in the search box. Also when using autoselect:true, the InfoWindow is populated with the result's full address.

If you have any ideas about these two problems it would be much appreciated.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Laura,

  It makes sense that the first source is the only one to work as that is what my sample is coded for:

var features = array.map(e.results[0], lang.hitch(this, function(result){

You would have to loop through all the items in the e.results array to work with the other source results.

The issue with results from the locator is they are different from the results of map layers. If you look at the attributes of the locators result feature you will see that the only attribute it has is score thus what you are seeing. So in this case you would have to add the name attribute to the features attributes before sending to the popup.

LauraMiles1
Occasional Contributor III

Thanks for all your help on this Robert. Adding outFields:

  • to the Locator brought in the rest of the attributes.
  • 0 Kudos
    LauraMiles1
    Occasional Contributor III

    Aha I just got the first part of my question - line 66 of the fiddle specifies e.results[0], which is clearly the array of results from the first pushed source. I will work with that.

    But if you have any idea why the Locator is only returning one attribute that would be great.

    0 Kudos