Search Widget and InfoTemplate, Domains, Subtypes

2550
0
11-23-2015 11:48 AM
DavidColey
Frequent Contributor

Hi All -

This is related to an earlier post of mine about migrating a search return from the geocoder widget's 'select' event to the new search widget's 'select-result' event.  Basically, the post and code Search Widget Results - Not Cleared from infoWindow

still applies, although in this earlier post the goal is to use an address to query one layer (say parcels), then use that result as an intersection to return info from a second layer (say floodzones).  Well, what if you just want to return the first layer?  In that case, just pass the select-result's event return feature geometry into the Query geometry, execute it and show your info window:

function showLocation(evt) {

  mapMain.graphics.clear();
  if (evt.source.name == "Search by Address" || evt.source.name == "Search by Street") {   
            
  qPoint = evt.result.feature.geometry;
            
  var queryParcels = new Query;
  queryParcels.geometry =  qPoint; //evt.result.feature.geometry;
  var parQuery = lyrParcels.selectFeatures(queryParcels,FeatureLayer.SELECTION_NEW);
            
  mapMain.infoWindow.setFeatures([parQuery]);
  mapMain.infoWindow.show(qPoint);
             
  if (qPoint != undefined) {
  mapMain.centerAndZoom(qPoint, 10);
  }
            
  } else {
       
  mapMain.infoWindow.show();
  }
}

But what about formatting your return when those results are pulling from subtyped or domained fields?  In the above snippet, not an issue because we've stepped outside of the Search dijit and so the infoWindow setFeatures is going to utilize the feature layer's previously defined popupTemplate.

But, if we are to utilize the full capability of the Search dijit, we want to be able to return a result not only by an address (or maybe an x,y) but also by each source layers' attributes themselves.  In that case, you can't run another Query as the Search is already doing that.  But because the Search doesn't utilize the popupTemplate, subtype and domain code descriptions become a formatting issue again with an infoWindow.  So what Michael Stranovsky (primarily Michael) and myself did was to take a terrific little snippet that Jeff Pace​ set up a long time ago to loop through nested arrays to get at those descriptions and pass them into a formatter that you set on any field in your infoTemplate that has subtypes or domains:

var subTypeVal;
getSubtypeDomain = function (fieldVal, fieldName){
     var sourceLayer = s.activeSource;
        //console.log(sourceLayer);
        if (sourceLayer.featureLayer.typeIdField!=null) {
            //console.log("Have Subtypes");
            if (fieldName==sourceLayer.featureLayer.typeIdField) {
                 array.forEach(sourceLayer.featureLayer.types, lang.hitch(this, function (lsf) {
                     if (fieldVal==lsf.id){
                         fieldVal=lsf.name;
                         subTypeVal=lsf.id;
                     }
                 }));
            } else {
                 array.forEach(sourceLayer.featureLayer.types, lang.hitch(this, function (lsf) {
                     if (lsf.id==subTypeVal){
                         array.forEach(lsf.domains[fieldName].codedValues, lang.hitch(this, function (domain) {
                            if (fieldVal==domain.code){
                                fieldVal=domain.name;
                            }
                         }));
                     }
                 }));
            }
        } else {
            //console.log("No Subtypes");
            subTypeVal=null;
            array.forEach(sourceLayer.featureLayer.fields, lang.hitch(this, function (ldf) {
                if (ldf.name==fieldName){
                    if (ldf.domain){
                        array.forEach(ldf.domain.codedValues, lang.hitch(this, function(domain){
                            if (fieldVal==domain.code){
                                fieldVal=domain.name;
                            }
                        }));
                    }
                }
            
            }));
        }
       return fieldVal;
   };

Basically what were doing is setting up 2 parameter formatter that is checking for subtypes first.  If a subtype field is found (typeIdField property) is found, (!=null) and while the subtypeField is set equivalent to the fieldName parameter, then go into each of the subtypes (while keeping fieldName and fieldVal in scope) and set up a call back for the fieldVal param to hitch the fieldVal param to a second call back function with parameter lsf  (layerSubtypeField).

While in this call back function if the id property of the fieldVal param is still equivalent to the lsf.id value, then set the fieldVal param equal to the subtype name and the subTypeVal var equal to the id or subtype code.  We now have each subtype description for the subtype field.

However, we still have to account for the different domains assigned to each subtype for each field.  This is common in the full water-wastewater data model for example. 

So, nested ELSE says for each subtype, call back the source layer and (while the id value for the lsf param is still assigned to the subTypeVal var), then for each subtype and field, find the domain's coded values and hitch the values to another call back function (domain parameter) that will match the domain codes to the fieldVal parameter , while finally setting the domain description (domain.name) to the fieldVal parameter. 

Now, what to do or how to account for a Search widget source with no subtypes?  In that case, complete the top level if with an ELSE that first resets subTypeVal to null (otherwise the loop is stuck) steps through each field and sets the domained field equivalent to the fieldName parameter, then for each field sets the codedValues for each domain equivalent to the fieldVal so we can then finally set the fieldVal equal to the domains description.  Close everything and return fieldVal for the function. 

Lastly, just set the function as a formatter in the infoTemplate:

infoTemplate: new InfoTemplate("${ProgramArea:getSubtypeDomain} Project", "<b>Name: </b>${ProjectName}</br><b>CIP#:</b> ${ProjectID}<br><b>Status: </b>${LifeCycleStatus:getetSubtypeDomain}" +
 "<br><b>Acreage:</b> ${Shape_Area:convertSqFt}" +
"<br><a target='_blank' href='https://somerulstring/${ProjectName}.jpg'><b>Project Detail</b></a>"), 

I welcome any and all comments and corrections to my attempt to describe this code.  But I will say that until such time as the Search can utilize the popupTempalate, I don't know of any other way to return subtype and coded value domain description in an infoTemplate.

Cheers-

David

0 Replies