Return Coded Domain Values in a dojo Data Grid?

1530
8
Jump to solution
09-27-2021 11:44 AM
luckachi
Occasional Contributor II

I am working with a dojo grid and I am wondering if there is a way to format or decode the values in 2 of the columns. Right now it is just displaying a 0, 1, 2, 3, 4 or 5 and I would like to be able to see the text associated with each number in the data grid because a number is really of no use to the user. Below is my code for populating the grid. OB_AREA and OB_DENSITY are the columns/fields in question.

/* Dojo  dgrid */
        var resultsGrid = declare([Grid, Selection, ColumnResizer]);
        var columns = [{
          // label: "Object ID",  //wasn't able to inject an HTML <div> with image here
          // field: "OBJECTID",
          // }, {
            label: "Observer Name",
            field: "OBSERVER"
          }, {
            label: "Observation Date",
            field: "DAY",
            formatter: formatTimestamp
          }, {
            label: "Latitude",
            field: "LATITUDE"
          }, {
            label: "Longitude",
            field: "LONGITUDE"
          }, {
            label: "Common Name",
            field: "Q_NAME"
          }, {
            label: "Genus",
            field: "GENUS"
          }, {
            label: "Species",
            field: "SPECIES"
          }, {
            label: "Area",
            field: "OB_AREA"
          }, {
            label: "Density",
            field: "OB_DENSITY"
          }, {
            label: "County",
            field: "COUNTY"
          }, {
            label: "State",
            field: "STATE"
          }, {
            label: "Country",
            field: "COUNTRY"
          }, {
            label: "Date Added",
            field: "ADD_DATE",
            formatter: formatTimestamp
          }];

        grid = new resultsGrid({
          bufferRows: Infinity,
          columns: columns,
          selectionMode: 'single'
        }, "grid");

        function formatTimestamp(value) {
         var inputDate = new Date(value);
         return dojo.date.locale.format(inputDate, {
           selector: 'date',
           datePattern: 'MM/dd/yyyy'
         });
        }

        grid.on('dgrid-select', function (event) {
            var lat = event.rows[0].data.LATITUDE;
            var long = event.rows[0].data.LONGITUDE;
            var pt = new Point(long,lat);
            view.goTo({
              target: pt,
              zoom: 17
            });
        });
/* Populate DGrid Table at bottom of page with query results*/
          var items = prjResults
          var TableFeatures = []
           array.forEach(items, function (feature) {
               var TableAttributes = {}
               var TableFields = Object.keys(feature.attributes)
               console.log(feature.attributes.OB_AREA);
               for (var i = 0; i < TableFields.length; i++) {
                   TableAttributes[TableFields[i]] = feature.attributes[TableFields[i]]
               }
               TableFeatures.push(TableAttributes)
           })

          var memStore = new Memory({
            data: TableFeatures,
            idProperty: "OBJECTID"
          });
          grid.set("collection", memStore);

 

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
JeffreyWilkerson
Occasional Contributor III

How about setting up another formatter?  Looks like a generic one would work for both fields, something like:

 

function numberToText(value) {
    var outText = "";
    if (value == 1) outText = "One";
    else if (value == 2) outText = "Two";
etc...
    else outText = "Unknown";
    return outText;
}

 

Then you can set that formatter to both of your fields:

 

}, {
    label: "Density",
    field: "OB_DENSITY",
    formatter: numberToText
}, {

 

 

View solution in original post

8 Replies
JeffreyWilkerson
Occasional Contributor III

How about setting up another formatter?  Looks like a generic one would work for both fields, something like:

 

function numberToText(value) {
    var outText = "";
    if (value == 1) outText = "One";
    else if (value == 2) outText = "Two";
etc...
    else outText = "Unknown";
    return outText;
}

 

Then you can set that formatter to both of your fields:

 

}, {
    label: "Density",
    field: "OB_DENSITY",
    formatter: numberToText
}, {

 

 

luckachi
Occasional Contributor II

Thank you @JeffreyWilkerson - that is exactly what I needed. I was leaning towards another formatter but wasn't quite sure how to put it all together.  I appreciate it!

0 Kudos
JeffreyWilkerson
Occasional Contributor III

FYI, this works well for a small number of possible values (numbers in this case).  But if it would get too large I would do something like make a dictionary (ordered pairs in Javascript) of all of the possible values {1:"One", 2:"Two", 3:"Three", etc. } and then use the value coming into the formatter function to determine the value to pass back.  It seemed like you were only dealing with a small list and the if/then/else would suffice.

 

luckachi
Occasional Contributor II

Hi Jeff, yes both fields only had 4-5 values so your example worked great.

It dawned on me afterwards that those values (at least for density) would change depending on another field. We have a field called Kingdom where it will be either Plant or Animal and then depending on what kingdom it is, it would have different densities. I assume I could do something similar to a nested if statement for this scenario. 

0 Kudos
JeffreyWilkerson
Occasional Contributor III

I think you can, however I don't know how to get the current value of a specific field when you are in the formatter function.  The formatter function is handling the row event and I'm not sure if it exposes what the selected row is.  You could string together a function to push out the current 'Kingdom' value on any row select and then pick that up with a formatter, I'm guessing.  It might look something like this (need to have the Dojo 'on' library loaded):

var sKingdom = "";
resultsGrid.on("dgrid-select", function (evt) {
    let cell = resultsGrid.cell(evt);
    sKingdom = cell.row.data.Kingdom;
});

dPlantDensities = {1:"Almost 1", 2:"Between 2 and 3", 3:"Below 4"};
dAnimalDensities = {1:"Just below 2", 2:"Between 2.5 and 3.4", 3:"Unknown"};
function getDensity(value) {
    var outText = "";
    if (sKingdom == "Plant") {
        if (value == 1) outText = dPlantDensities[1];
        else if (value == 2) outText = dPlantDensities[2];
    else {
        if (value == 1) outText = dAnimalDensities[1];
        else if (value == 2) outText = dAnimalDensities[2];
etc...
    }
    return outText;
}

 Maybe someone can figure out how to access the row directly from the formatter function but this might work.

0 Kudos
luckachi
Occasional Contributor II

Thank you Jeff for your insight and knowledge. I appreciate your time with this and I will dive into this today.

0 Kudos
JeffreyWilkerson
Occasional Contributor III

Luckachi,

Not sure if you have tried the field options method, but that could limit the user's selection to only a specified range of values.  I am using it on an asset field that I pull all of the potential assets out using a call to the web service prior to presenting the Grid.  The field is set up using this syntax in the Grid columns setup:

{ field: 'AmenityType', 
    label: 'Type', 
    editor: Select, 
    editOn: 'dblclick', 
    editorArgs: { 
        style: { width: "66px;" }, 
        options: optionsAmenityType 
    } 
},

The optionsAmenityType list is built by calling the web service like this:

// Query for AmenityType domain information
let optionsAmenityType = [];
let amenityTypeDomainURL = "https://services2.arcgis.com/2t1927381mhTgWNC/ArcGIS/rest/services/Regional_Bus_Stops/FeatureServer/1?f=pjson";
esriRequest(amenityTypeDomainURL, {
        responseType: "json"
    }).then(function (response) {
        let lstTypes = response.data.fields[1].domain.codedValues;
        for (var i = 0; i < lstTypes.length; i++) {
            var curType = lstTypes[i];
            optionsAmenityType.push({ value: curType.code, label: curType.name });
        }
    })
        .catch(function (error) {
            console.error("AmenityType Domain Error: " + error);
        });

It seems to work well and doesn't impact performance that much.  My biggest issue is trying to get dGrid to look good as it seems the styles are not that well documented and changing one thing impacts 2 others. 

But this process might work in your instance if before the Grid deployment you could get the specific 'kingdom' to use, then you could build a list of options (through either a web service call like I did or just specifying the values in the code (not always best because then you are locked into any value changes being done in the code)) and then the user would only be able to select one of the values for that particular 'kingdom'.  

Just a thought.  And if you have any good dGrid styling ideas please let me know.

0 Kudos
luckachi
Occasional Contributor II

@JeffreyWilkerson I was able to find a solution using the get method on the column. In case anyone else will find this helpful, see below: 

 

{
  label: "Density",
  field: "OB_DENSITY",
  get: function(obj){
     if (obj.KINGDOM == 0) {if (obj.OB_DENSITY == 0) {return "NA"};}
     if (obj.KINGDOM == 0) {if (obj.OB_DENSITY == 1) {return "Sparse (scattered individual stems or very small stands)"};}
     if (obj.KINGDOM == 0) {if (obj.OB_DENSITY == 2) {return "Patchy (a mix of sparse and dense areas)"};}
     if (obj.KINGDOM == 0) {if (obj.OB_DENSITY == 3) {return "Dense (greater than 40% of the area)"};}
     if (obj.KINGDOM == 0) {if (obj.OB_DENSITY == 4) {return "Monoculture (nearly 100% of area)"};}
     if (obj.KINGDOM == 1) {if (obj.OB_DENSITY == 0) {return "NA"};}
     if (obj.KINGDOM == 1) {if (obj.OB_DENSITY == 1) {return "Few (<5)"};}
     if (obj.KINGDOM == 1) {if (obj.OB_DENSITY == 2) {return "Many (5+)"};}
  }
},