Good Day
I have a weird issue where my PrintTask outputs are missing legend, sometimes, but not others, and I can't find a pattern as to why. I have a unique value render setting with ~160 different values in it, and on most of the maps I use a valueExpression to set the renderer.
If I take two maps which use the same valueExpression, literally the same one, and compare them, one will generate with legends, and the other won't.
Map 1:
Map 2:
The valueExpression: When($feature.aType == 3 && $feature.ci > -10 && $feature.ci <= 40, 'condition_3_Crititcal',$feature.aType == 3 && $feature.ci > 40 && $feature.ci <= 50, 'condition_3_Poor',$feature.aType == 3 && $feature.ci > 50 && $feature.ci <= 65, 'condition_3_Fair',$feature.aType == 3 && $feature.ci > 65 && $feature.ci <= 90, 'condition_3_Good',$feature.aType == 3 && $feature.ci > 90 && $feature.ci <= 99, 'condition_3_Excellent',$feature.aType == 3 && $feature.ci > 99 && $feature.ci <= 100, 'condition_3_Perfect',$feature.aType == 3 && $feature.ci > -10 && $feature.ci <= 0, 'condition_3_Not Defined','condition_Not Defined')
That is the valueExpression shared by both maps, the first will generate a legend, the second won't. This is my print function:
public printMap(): void {
const titleText = 'Map: ';
/* let layerLegend = new LegendLayer();
let layerIds = [];
this._view.map.layers.forEach((layer) => {
layerIds.push(layer.id);
})
layerLegend.layerId = "layer1";
layerLegend.subLayerIds = layerIds;
legendLayers: [layerLegend],
*/
const template = new PrintTemplate({
format: 'pdf',
layout: 'a4-landscape',
layoutOptions: {
authorText: 'Blah',
titleText
},
});
const params = new PrintParameters({
view: this._view,
template,
});
//
// NOTE: Start the print progress spinner
//
this.printProgress = true;
const printURL = 'https://utility.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task';
PrintTask.execute(printURL, params).then((result) => {
//
// NOTE: Stop the spinner and open the print output
// into a new tab.
//
this.printProgress = false;
this.forceChange();
window.open(result.url);
}, () => {
this.alert.errorDialog('Print Error', 'Please try again or contact support!');
this.printProgress = false;
this.forceChange();
});
}
Is there any reason for this behaviour? I'm I missing something in the PrintTemplate or PrintParameters?
On a strange note, I don't use a valueExpression, I always get a legend on the print output:
I suspect the problem has to do with the use of the valueExpression, so is there a way to pass my legend / layer information directly to the print task?
Thanks
Solved! Go to Solution.
Good Day
I found a solution! I was previous performing a featureEffect query to show and hide layers, setting excluded layers to opacity 0%. This was working great until yesterday when we noticed I could still interact with the features (my fault, I should have thought about that!).
I decided to move from the featureEffect query to the layerView filter query, and now all PrintTasks are showing up with legends intact. It seems for some odd reason that the “featureEffect” was causing the problem.
Hopefully this can help others in the future!
Thanks for your help.
Hello @AndrewMurdoch1, thanks for posting your question here. A couple questions: which version of the API are you using? And is there a difference between the layer types when the legend items print vs. doesn't print?
Good Day
API Version 4.25.5
"@arcgis/core": "4.25.5",
"@esri/arcgis-rest-auth": "3.6.0",
"@esri/arcgis-rest-feature-layer": "3.6.0",
"@esri/arcgis-rest-portal": "3.6.0",
"@esri/arcgis-rest-request": "3.6.0",
"@esri/arcgis-rest-types": "3.6.0",
"@esri/calcite-components": "1.0.2",
All the layers are Feature Layers, here is the way they're set up:
private buildFeatureSettings(geometryType: string, data: any, metaLayer: boolean = false): any {
const layerLabelClass = new LabelClass({
labelExpressionInfo: {expression: '$feature.label'},
symbol: {
type: 'text',
color: 'black',
haloSize: 1,
haloColor: 'white'
}
});
const renderSetting = this.buildRenderSettingForLayer(geometryType);
return {
fields: metaLayer ? this._metaFields : this._fields,
geometryType: geometryType,
globalIdField: 'assetSectionId',
id: metaLayer ? `meta-${data[0].attributes.layerId}` : this.generateUniqSerial(),
labelingInfo: [layerLabelClass],
objectIdField: 'ObjectID',
outFields: ['*'],
renderer: renderSetting,
source: data,
title: '',
visible: true
}
}
“renderSetting” is the same for all layers, it's ~160 Unique Value Render Settings. One thing I have noticed is that the layers which don't use “valueExpressions” are always showing up, I only see this odd behaviour when I use “valueExpressions”, but it's not constant.
Any help would be greatly appreciated 🙂
Thanks
If it matters, this is buildRenderSetting
private buildRenderSettingForLayer(geometryType: string = 'polyline'): UniqueValueRenderer {
let renderSetting;
if (this.gisFlag) {
if (geometryType === 'point' && this.tabIndex === 0) {
// NOTE: The first tab in the GIS Page is a "Picture Marker"
renderSetting = this.render.getUniqueRenderSetting(`picture-point`);
} else {
// NOTE: Handle lines / polygons
renderSetting = this.render.getUniqueRenderSetting(geometryType);
}
} else {
// NOTE: Handle lines / polygons
renderSetting = this.render.getUniqueRenderSetting(geometryType);
}
if (this.gisFlag) {
const gisFieldInformation = this.whichGISField();
renderSetting.field = gisFieldInformation.field;
renderSetting.valueExpression = null;
if (gisFieldInformation.valueExpression !== '') {
renderSetting.field = '';
renderSetting.valueExpression = gisFieldInformation.valueExpression;
this.hostLayerState = this.render.getLegend(gisFieldInformation.legendType);
this.hostLayerState.forEach((layerState) => {
layerState.field = gisFieldInformation.legendField;
})
}
} else if (this.performance) {
if (!this._year) {
this._year = 2022;
}
renderSetting.field = '';
const valueExpression =
this.render.getValueExpression('CONDITION');
renderSetting.valueExpression =
valueExpression.replaceAll('FIELD_REPLACE_TEXT', `$feature.F${this._year}`);
} else if (this._capitalPlan || this._alignment) {
renderSetting.field = `F${this._year}`;
renderSetting.valueExpression = '';
}
console.log('Render Setting - Build Render Setting');
console.log(_.cloneDeep(renderSetting));
return renderSetting;
}
Hmm, can you check the network traffic and compare the two print requests? Open the developer tools in the browser of choice, and look at the execute request when printing and compare the two payloads. My hunch is that there will be a difference, but even if there's not, it would still be helpful to know.
Thanks for the suggestion, I'm kind of baffled as to why I didn't think of that myself. The “featureCollection” object is missing when the legend isn't present. When I don't have the “featureCollection”, I have “imageData”, and I think that's what is causing the problem.
Should I be adding in LegendLayers into the Print Parameters? https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-LegendLayer.html
If so, what do I pass for layerId and subLayerId? I would assume I get the layerId with:
const legendLayers = []
this._view.map.layers.forEach((layer) => {
let legendLayer = new LegendLayer();
legendLayer.layerId = layer.id;
legendLayer.subLayerId = [] // NOTE: I don't know what to pass for this
});
I already to do this, but I keep getting three boxes, Red, Green and Blue showing up, which I think it due to incorrectly assembling the legend layers array.
If run a featureEffect filter, or manually replace the render setting on a feature layer with layer.renderer = newRenderSetting, will that cause an issue?
Thanks!
Good Day
I found a solution! I was previous performing a featureEffect query to show and hide layers, setting excluded layers to opacity 0%. This was working great until yesterday when we noticed I could still interact with the features (my fault, I should have thought about that!).
I decided to move from the featureEffect query to the layerView filter query, and now all PrintTasks are showing up with legends intact. It seems for some odd reason that the “featureEffect” was causing the problem.
Hopefully this can help others in the future!
Thanks for your help.
Excellent, thanks for sharing the follow-up solution. My hunch is that the "featureEffect" was sending the layer as a screenshot (known limitation) and layers sent as screenshots do not appear in the printed legend (another known limitation).
Known limits for printing are documented here:
https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-print.html
Thanks!