I have a pretty complicated data expression and advanced formatting expression that used to work before the Dashboard update. The data expression looks for data entries that have been submitted via survey123 forms for every month of the year, it is a two part survey and they have to hit a 'Entry Complete?' question that fills in a field with "Complete" or leaves blank if not selected. The data expression returns a sort of binary table that returns 0 if not submitted for that month, 0.5 if submitted but not incomplete and 1 if complete. And then I have an advanced formatting expression that returns a sort of 'progress bar' that returns red colors if not submitted, yellow colors if incomplete and green colors if submitted.
After the update I noticed that all my bars were returning red colors and just from the advanced formatting expression returning null values, but my data table still looked good. The only fix I've found has been to add the <field/month year> in the template, I found a way to hide it via the source html. But this is only a temporary fix since in future years, it will need to updated with the new years and won't do it dynamically anymore.
I've attached a photo of what the output is supposed to look like.
My data expression is:
// add the feature layer
var fs = FeatureSetByPortalItem(Portal('https://www.arcgis.com'), '7b5c985c865d405180e2f613cb9e40fa', 0, ['nursery', 'MonitoringDate', 'EntryComplete'], false);
// initialize dictionary
var monitoringData = {
'fields': [{'name': 'nursery', 'type': 'esriFieldTypeString'}],
'geometryType': '',
'features': []
};
// dynamic month-year columns for the last 2 years
var currentYear = Year(Now());
var years = [currentYear - 1, currentYear]; // Include the last two years
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
// month-year columns based on the last 2 years
var monthYearColumns = [];
for (var y in years) {
for (var m in months) {
var colName = months[m] + " " + Text(years[y]);
Push(monthYearColumns, colName);
Push(monitoringData.fields, {'name': colName, 'type': 'esriFieldTypeDouble'}); // Double to allow 0.5
}
}
// empty record dictionary to store the monitoring data by nursery
var nurseryDict = {};
// classify surveys from the dataset
for (var feature in fs) {
var nurseryName = feature['nursery'];
var monitoringDate = feature['MonitoringDate'];
var entryComplete = feature['EntryComplete'];
// make sure monitoring date is valid
if (!IsEmpty(monitoringDate)) {
var monthIndex = Month(monitoringDate); // Get the month (0-indexed)
var yearValue = Year(monitoringDate);
var monthYearKey = months[monthIndex] + " " + Text(yearValue);
// survey status (0 = no data, 0.5 = incomplete, 1 = complete)
var entryStatus = IIf(IsEmpty(entryComplete), 0.5, IIf(entryComplete == "Complete", 1, 0));
// make sure the nursery exists in the dictionary, if not, create it
var nurseryKey = Text(nurseryName);
if (!HasKey(nurseryDict, nurseryKey)) {
var record = {'nursery': nurseryName};
// initialize all months and years to 0 (indicating no survey filled)
for (var col in monthYearColumns) {
record[monthYearColumns[col]] = 0;
}
nurseryDict[nurseryKey] = record;
}
// set this month-year to the determined completion status
nurseryDict[nurseryKey][monthYearKey] = entryStatus;
}
}
// convert the dictionary into a FeatureSet
for (var key in nurseryDict) {
Push(monitoringData.features, {'attributes': nurseryDict[key]});
}
// return
return FeatureSet(Text(monitoringData));
My advanced formatting expression is:
// colors
var completedColor = "#006400";
var incompleteColor = "#FF0000";
var partialColor = "#FFA500";
// Months
var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
// years
var years = [];
var currentYear = Year(Now());
for (var i = 0; i < 2; i++) {
Push(years, Text(currentYear - i));
}
// layout
var boxWidth = 22;
var boxHeight = 12;
var gap = 6;
var startX = 60;
var startY = 20;
var svgWidth = 750;
var svgHeight = 160;
var svg = '<svg width="' + svgWidth + '" height="' + svgHeight + '">';
// month labels
for (var i = 0; i < 12; i++) {
var xPos = startX + (i * (boxWidth + gap));
svg += '<text x="' + (xPos + 1) + '" y="10" font-size="9">' + months[i] + '</text>';
}
// rows
for (var y in years) {
var year = years[y];
var yearNum = Number(year);
var yPos = startY + (y * (boxHeight + 14));
svg += '<text x="10" y="' + (yPos + 10) + '" font-size="11" font-weight="bold">' + year + '</text>';
for (var i = 0; i < 12; i++) {
var fieldName = months[i] + " " + year;
var monthValue = DefaultValue($datapoint[fieldName], 0);
var color;
if (monthValue == 1) {
color = completedColor;
} else if (monthValue == 0.5) {
color = partialColor;
} else {
color = incompleteColor;
}
var xPos = startX + (i * (boxWidth + gap));
svg += '<rect x="' + xPos + '" y="' + yPos +
'" width="' + boxWidth + '" height="' + boxHeight +
'" fill="' + color + '" rx="2" ry="2"/>';
}
}
// legend
var legendY = startY + (Count(years) * (boxHeight + 14)) + 20;
svg += '<text x="10" y="' + legendY + '" font-size="12" font-weight="bold">Survey Status</text>';
var ly = legendY + 12;
// incomplete
svg += '<rect x="10" y="' + ly + '" width="14" height="10" fill="' + incompleteColor + '" rx="2"/>';
svg += '<text x="28" y="' + (ly + 9) + '" font-size="10">Not Submitted</text>';
// partial
svg += '<rect x="180" y="' + ly + '" width="14" height="10" fill="' + partialColor + '" rx="2"/>';
svg += '<text x="198" y="' + (ly + 9) + '" font-size="10">Incomplete</text>';
// Completed
svg += '<rect x="330" y="' + ly + '" width="14" height="10" fill="' + completedColor + '" rx="2"/>';
svg += '<text x="348" y="' + (ly + 9) + '" font-size="10">Completed</text>';
svg += '</svg>';
return {
attributes: {
svg: svg
}
};
The fix I did:
<p>
<span style="font-size:18px;"><i>Nursery:</i> <strong>{field/nursery}</strong></span>
</p>
<p>
</p>
<p>
{expression/svg}
</p>
<div style="display:none;">
{field/Jan 2025}{field/Feb 2025}{field/Mar 2025}{field/Apr 2025}{field/May 2025}{field/Jun 2025}{field/Jul 2025}{field/Aug 2025}{field/Sep 2025}{field/Oct 2025}{field/Nov 2025}{field/Dec 2025}{field/Jan 2026}{field/Feb 2026}{field/Feb 2026}{field/Mar 2026}{field/Apr 2026}{field/May 2026}{field/Jun 2026}{field/Jul 2026}{field/Aug 2026}{field/Sep 2026}{field/Oct 2026}{field/Nov 2026}{field/Dec 2026}
</div>