How to show field alias instead of field name in PopupTemplate

1793
3
Jump to solution
03-20-2018 07:37 AM
StanLambert
New Contributor II

I'm trying to use the out-of-the-box functionality for PopupTemplate but I'm struggling with how to show the field alias instead of the field name. I've tried two ways of creating the content for the popup: using a Javascript function to render the content and using a dynamically-generated fieldInfos object. 

1. The Javascript function is supplied three parameters: key, value and data. The key is the field name, the value is the field value, and data is a list of key-values for the entire layer.  The field alias is not available to this function.

2. All of the examples of using fieldInfos to define the content show the label as hard-coded. I realize the examples have to be kept simple but hard-coding the labels is not practical in my situation. I have dozens of layers,  each with 50 or more attributes. I need to dynamically create the content for the popup.

I see the query tasks being executed when I click on a feature and I see the fieldAlias object being returned. I just don't know how to access it within the popup template configuration.

Any help is greatly appreciated.

0 Kudos
2 Solutions

Accepted Solutions
MunachisoOgbuchiekwe
New Contributor III

Hello Stan, 

If I am understanding your question correctly, you can do the following... 

  1. Query the Feature Layer and the promise response should give you back the field alias. 
  2. Replace the Feature Layer popupTemplate with the response from the Feature Layer query. 

You can access the alias by providing the promise a callback function, then you can just call the parameter you passed into the callback function. 

require([
      "esri/Map",
      "esri/layers/FeatureLayer",
      "esri/views/MapView",
      "dojo/domReady!"
    ], function(
      Map,
      FeatureLayer,
      MapView
    ) {

      // Create the map
      var map = new Map({
        basemap: "gray"
      });

      // Create the MapView
      var view = new MapView({
        container: "viewDiv",
        map: map,
        center: [-73.950, 40.702],
        zoom: 3
      });

      var template = { // autocasts as new PopupTemplate()
        title: "Test PopUp Template: {Incident Number}",
        content: "<p>As of 2015, <b>{MARRIEDRATE}%</b> of the population in this zip code is married.</p>" +
          "<ul><li>{MARRIED_CY} people are married</li>" +
          "<li>{NEVMARR_CY} have never married</li>" +
          "<li>{DIVORCD_CY} are divorced</li></ul>",
        fieldInfos: [{
          fieldName: "MARRIED_CY",
          format: {
            digitSeparator: true, // Use a comma separator for large numbers
            places: 0 // Sets the number of decimal places to 0 and rounds up
          }
        }, {
          fieldName: "NEVMARR_CY",
          format: {
            digitSeparator: true,
            places: 0
          }
        }, {
          fieldName: "DIVORCD_CY",
          format: {
            digitSeparator: true,
            places: 0
          }
        }]
      };

      // Reference the popupTemplate instance in the
      // popupTemplate property of FeatureLayer
      var featureLayer = new FeatureLayer({
        url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessmentStatePlane/FeatureServer...",
        outFields: ["*"],
        popupTemplate: template
      });
      
      featureLayer.load().then(function(){
        var query = featureLayer.createQuery();
        query.returnGeometry = true; 
        query.where = "1=1";
        
        featureLayer.queryFeatures(query).then(function(results){
          featureLayer.popupTemplate.content = "Alias for incidentid is: " + results.fields[1].alias;
        });
      });
        
      map.add(featureLayer);
    });‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

0 Kudos
DheerajGambhir
New Contributor II

Hi All,
I was also struggling for this only and can not find any solution but developed a workaround, Hope this may help others as well. Please find below code.

let popupFunction = function(event: any) {
        let fieldalias: any = {};
        event.graphic.sourceLayer.fields.forEach((element: any) => {
          fieldalias[element.name] = element.alias;
        });
        let attributes = event.graphic.attributes;
        let fields = Object.keys(attributes)
        let values = Object.values(attributes);
        
let html = '<table class="popupTable">';
        for(let i=0; i<fields.length; i++){
          html = html + '<tr><td class="fieldStyle">'+ fieldalias[fields[i]] + '</td><td class="valueStyle">' + values[i] + '</td></tr>'
        }
        html = html + '</table>'
       return html;
}

View solution in original post

0 Kudos
3 Replies
MunachisoOgbuchiekwe
New Contributor III

Hello Stan, 

If I am understanding your question correctly, you can do the following... 

  1. Query the Feature Layer and the promise response should give you back the field alias. 
  2. Replace the Feature Layer popupTemplate with the response from the Feature Layer query. 

You can access the alias by providing the promise a callback function, then you can just call the parameter you passed into the callback function. 

require([
      "esri/Map",
      "esri/layers/FeatureLayer",
      "esri/views/MapView",
      "dojo/domReady!"
    ], function(
      Map,
      FeatureLayer,
      MapView
    ) {

      // Create the map
      var map = new Map({
        basemap: "gray"
      });

      // Create the MapView
      var view = new MapView({
        container: "viewDiv",
        map: map,
        center: [-73.950, 40.702],
        zoom: 3
      });

      var template = { // autocasts as new PopupTemplate()
        title: "Test PopUp Template: {Incident Number}",
        content: "<p>As of 2015, <b>{MARRIEDRATE}%</b> of the population in this zip code is married.</p>" +
          "<ul><li>{MARRIED_CY} people are married</li>" +
          "<li>{NEVMARR_CY} have never married</li>" +
          "<li>{DIVORCD_CY} are divorced</li></ul>",
        fieldInfos: [{
          fieldName: "MARRIED_CY",
          format: {
            digitSeparator: true, // Use a comma separator for large numbers
            places: 0 // Sets the number of decimal places to 0 and rounds up
          }
        }, {
          fieldName: "NEVMARR_CY",
          format: {
            digitSeparator: true,
            places: 0
          }
        }, {
          fieldName: "DIVORCD_CY",
          format: {
            digitSeparator: true,
            places: 0
          }
        }]
      };

      // Reference the popupTemplate instance in the
      // popupTemplate property of FeatureLayer
      var featureLayer = new FeatureLayer({
        url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessmentStatePlane/FeatureServer...",
        outFields: ["*"],
        popupTemplate: template
      });
      
      featureLayer.load().then(function(){
        var query = featureLayer.createQuery();
        query.returnGeometry = true; 
        query.where = "1=1";
        
        featureLayer.queryFeatures(query).then(function(results){
          featureLayer.popupTemplate.content = "Alias for incidentid is: " + results.fields[1].alias;
        });
      });
        
      map.add(featureLayer);
    });‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
StanLambert
New Contributor II

Thank you for the information. It is very helpful.

After further review however, I believe that it is just not possible to do what I want to do. 

I need a generic function that iterates through all of the fields of the feature layer, provides custom formatting for each field value when necessary, ignores some fields based on the field value (null for example) and creates a simple HTML table showing field alias and field value.  The content has to be created dynamically when the feature is clicked on because I need to know the values returned in order to format the values and ignore null values when creating the HTML.

The strategy that comes closest to working for me is the technique of using a function to render each value, for example {fieldName:renderValue} where renderValue is a global JavaScript function that takes the value and field name as the first two parameters. Using this technique I can dynamically create a content string comprised of all of the {fieldName:renderValue} objects wrapped in the appropriate HTML tags to create a table. Each call to renderValue allows me to take the appropriate action based on the field value - format it, ignore it, add to it, etc. So my content string would look like this:

<table>{fieldName1:renderValue}{fieldName2:renderValue}...{lastField:renderValue}</table>

and each call to renderValue creates an HTML row inside of the table tags. Unfortunately, I only have the field name and field value to work with in this function, not the field alias.

The other technique that I thought would work would be to use a Promise as the content for the popup. I thought I would be able to write a function that executes a query against the REST service, process the results in the callback and dynamically create the content for the popup. Unfortunately, any function assigned to the 'content' property of the popup, is only passed the Graphic that was clicked on.  I can't execute a query using the graphic. Again, whatever I do has to be generic. The sample that shows the use of a Promise has a QueryTask predefined that can be used to query the REST service.  All I have to work with if I assign a function to the content is the graphic that was clicked on.  It does not contain the url of the feature layer.

I realize that what I want to accomplish can be done by writing it all myself, including the popup window, but I really wanted to work within the existing Popup because of the built-in functionality it has - resizing, docking, actions, zooming.  It really is a nice widget and I don't want to try and re-create all of that functionality.

0 Kudos
DheerajGambhir
New Contributor II

Hi All,
I was also struggling for this only and can not find any solution but developed a workaround, Hope this may help others as well. Please find below code.

let popupFunction = function(event: any) {
        let fieldalias: any = {};
        event.graphic.sourceLayer.fields.forEach((element: any) => {
          fieldalias[element.name] = element.alias;
        });
        let attributes = event.graphic.attributes;
        let fields = Object.keys(attributes)
        let values = Object.values(attributes);
        
let html = '<table class="popupTable">';
        for(let i=0; i<fields.length; i++){
          html = html + '<tr><td class="fieldStyle">'+ fieldalias[fields[i]] + '</td><td class="valueStyle">' + values[i] + '</td></tr>'
        }
        html = html + '</table>'
       return html;
}
0 Kudos