Select to view content in your preferred language

Sort the Search Widget suggestionTemplate; NULL values on bottom

558
4
Jump to solution
11-16-2023 02:33 PM
ToddGurnee
New Contributor III

I am attempting to sort my Search widget's suggestionTemplate's return in ascending order. The widget is looking at 4 fields all in a single feature class. This is an employee locator app and the Search fields in this feature class are for Employee Name, Room, Office Phone, and Cell phone. Using orderByFields for Employee Name technically works but if a room is empty (Null value for Employee Name) it is now at the top of the return. I am looking to have occupied rooms return first and then empty rooms. Basically Null values for Employee Name at the bottom of the suggestions.

Hope I explained it coherently. I've been working with ESRI support but they haven't found a solution.

This post is connected to my previous one: https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/remove-null-values-from-the-searc...

@JoelBennett thanks again for solving that one!

Here is my code for the Search widget:

    const searchWidget = new Search({
      view: view,
      allPlaceholder: "Search for Rooms, People, Last 4 of Phone ",
      includeDefaultSources: false,
      locationEnabled: false,
      sources: [{
          layer: SearchSpace,
          // searchTemplate: ["KNOWNAS", "SPACEID","PHONE_EXT","MOBILE"],
          searchFields: ["KNOWNAS", "SPACEID","PHONE_EXT","MOBILE"],
         
          suggestionTemplate: {
           
            replaceAll: function(a, b) {
                           
              var piecesIn = [
                ["{KNOWNAS}", ""],
                ["{SPACEID}", ""],
                ["Ext: {PHONE_EXT}", "Ext: "],  
                ["Cell: {MOBILE}", "Cell: "],
                ["(Building {BUILDING})", " "]
              ];

              var piecesOut = [];
                console.log(piecesOut + "piecesOut1")
              piecesIn.forEach(function(pieceIn) {
                var pieceOut = pieceIn[0].replaceAll(a, b);
     
                if (pieceOut !== pieceIn[1])
                  piecesOut.push(pieceOut);
                    console.log(piecesOut + "piecesOut2")
              });
     
              if (piecesOut.length === 0)
                return "";
              else if (piecesOut.length === 1)
                return piecesOut[0];
              else
                return piecesOut.join(",  ");  
            },
          },
         
          //suggestionTemplate: "Name: {KNOWNAS}, Room: {SHORTNAME}, Phone: {PHONE}, Cell: {MOBILE}, {WORKSITE} ",
          exactMatch: false,
          maxResults: 50,
          minSuggestCharacters: 0,
          maxSuggestions: 50,
          outFields: ["*"],
          orderByFields: ["KNOWNAS ASC"],
          localSearchDisabled: true,
          placeholder: "Search for Rooms, People, Last 4 of Phone",
          zoomScale: 500
      },
  ]
  });
 
  //Add Wildcard to Search widget
 
  esriConfig.request.interceptors.push({
    urls: /\/query/,
    before({ requestOptions }) {
        if (/LIKE '[^%]/g.test(requestOptions.query?.where)) {
            ('like request intercepted', requestOptions);
            requestOptions.query.where = requestOptions.query.where.replace(/ LIKE \'/g, ' LIKE \'%');
        }
    }
  })  
 
  // Create the Search Expand widget
  const SCExpand = new Expand({
    view: view,
    content: searchWidget,
    expandIconClass: "esri-icon-search",
    expandTooltip: "Open Search",
    collapseTooltip: "Close Search",
    group: "Widgets",
    autocollapse: true,
    closeOnEsc: function() {
      return searchWidget.activeMenu === "none"
    },
    expanded: false
  })

  // close the expand whenever a search is complete
  searchWidget.watch("activeBookmark", () => {
    SCExpand.collapse();
    }),

//-------------------------------------------------------
  searchWidget.on("select-result", function(event){  
    view.goTo({
      scale: 50
    });
 
0 Kudos
1 Solution

Accepted Solutions
JoelBennett
MVP Regular Contributor

Ok, so the problem here is that the response of the query is in a binary (pbf) format, not JSON.  There are a couple ways to deal with this, and I would recommend starting with the easiest, which is to force the queries to use JSON format, and not pbf.  To do that, add the following somewhere before the SDK is loaded:

<script type="text/javascript">
	window.dojoConfig = {
		has: {
			"featurelayer-pbf": false
		}
	};
</script>

 

If you already have a dojoConfig object, you can consolidate the above with that.

View solution in original post

4 Replies
JoelBennett
MVP Regular Contributor

It seems that if you added an "after" function to your interceptor, you could use it to adjust the order as desired:

  esriConfig.request.interceptors.push({
    urls: /\/query/,
    before({ requestOptions }) {
        if (/LIKE '[^%]/g.test(requestOptions.query?.where)) {
            ('like request intercepted', requestOptions);
            requestOptions.query.where = requestOptions.query.where.replace(/ LIKE \'/g, ' LIKE \'%');
        }
    },
    after: function(response) {
        var notNulls = [];
        var nulls = [];

        response.data.features.forEach(function(feature) {
            if (feature.attributes.KNOWNAS === null)
                nulls.push(feature);
            else
                notNulls.push(feature);
        });

        response.data.features = notNulls.concat(nulls);
    }
  }) 
ToddGurnee
New Contributor III

Thanks Joel,

Unfortunately when we implemented your code our layers no longer displayed in our app and the Search widget didn't return anything. The only error that was returned was in the Chrome Developer's tool 

ToddGurnee_0-1700583270131.png

Here is how we added the code:

 //Add Wildcard to Search widget
 
  esriConfig.request.interceptors.push({
    urls: /\/query/,
    before({ requestOptions }) {
        if (/LIKE '[^%]/g.test(requestOptions.query?.where)) {
            ('like request intercepted', requestOptions);
            requestOptions.query.where = requestOptions.query.where.replace(/ LIKE \'/g, ' LIKE \'%');
        }
    },
    after: function(response) {
      var notNulls = [];
      var nulls = [];

      response.data.features.forEach(function(feature) {
          if (feature.attributes.KNOWNAS === null)
              nulls.push(feature);
          else
              notNulls.push(feature);
      });

      response.data.features = notNulls.concat(nulls);
    }
  });  
 
Not sure if we missed something. We did try different methods of troubleshooting but with no luck. We appreciate your time and assistance with this. If you have anymore ideas we'd love to hear them.
0 Kudos
JoelBennett
MVP Regular Contributor

Ok, so the problem here is that the response of the query is in a binary (pbf) format, not JSON.  There are a couple ways to deal with this, and I would recommend starting with the easiest, which is to force the queries to use JSON format, and not pbf.  To do that, add the following somewhere before the SDK is loaded:

<script type="text/javascript">
	window.dojoConfig = {
		has: {
			"featurelayer-pbf": false
		}
	};
</script>

 

If you already have a dojoConfig object, you can consolidate the above with that.

ToddGurnee
New Contributor III

Thanks Joel, you did it again! Thank you so much.

0 Kudos