MapImageLayer Sublayers Renderer

685
10
08-28-2018 05:19 AM
Highlighted
Occasional Contributor

Can you use a Unique Value Renderer function for a MapImageLayer sublayer? 

When I try using an existing field name as a string it works, but when I try to set up a function like in the api documentation I get the error:

[esri.renderers.UniqueValueRenderer] .field: cannot write field to JSON since it's not a string value

The code I am using:

function test(feature){
}
var renderer = {
type: "unique-value", // autocasts as new UniqueValueRenderer()
field: test,

Is there a way to make it work?

Reply
0 Kudos
10 Replies
Highlighted
MVP Esteemed Contributor

Matthieu,

   I can confirm the same error on my end. Sounds like a bug as there is no limitation stated in the help documentation about this not being supported for MapImageLayers. You should contact esri tech support to report the bug.

Highlighted
Esri Regular Contributor

I also confirm the same behavior. Thank you for sharing this information. Apologize for the inconvenience. 

To give you a heads-up: at the next release (4.9), we anticipate removing the ability to pass a function to the `field` property, and only allow a string, so this issue would become the expected behavior.

One potential workaround would be to use the valueExpression property as an alternative to using the `field` property.

Another potential workaround , if you are using version 4.7 or 4.8 of the API, would be to use the createFeatureLayer() method to create a feature layer from the sublayer, then you can use a function for the `field` property. I have tested this and it works properly.

Hope this helps,

Noah

Highlighted
Occasional Contributor

Thank you for the replies. I am using the createFeatureLayer instead.

At the next release, will you remove the ability to pass a function to the field property even for feature layers? So I know if I should stop using it altogether and go for the valueExpression (that only works for feature layers right?)

Reply
0 Kudos
Highlighted
Esri Regular Contributor

Correct, at the next release (4.9), we anticipate removing the ability to pass a function to the `field` property of renderers.

UniqueValueRenderer | API Reference | ArcGIS API for JavaScript 4.8 

Using the valueExpression property as an alternative to using the `field` property should be valid for featureLayer and mapImageLayer, but please note the Known Limitation for sublayers (linked to below).

Sublayer | API Reference | ArcGIS API for JavaScript 4.8 

Highlighted
New Contributor II

I'm having a similar problem and just found this thread. My issue arises when enabling WebGL for my feature layers with version 4.8. After setting up the renderer with a function in the field property I get the same error reported above:

 

[esri.renderers.UniqueValueRenderer] .field: cannot write field to JSON since it's not a string value

 

My big concern here is the direction moving forward. If we remove the ability to pass a function in for the field property that could have a big impact to our application. Arcade expressions are fine if all the data you need to use is in your feature layer, but that is not the case in my scenario. We have additional data within the app that helps to resolve the string that field ultimately gets set to. We would not be able to access this additional data from an Arcade expression. Is there any thought being given to this sort of use case with the retirement of this feature?

Highlighted
Regular Contributor

This is a reply to all the questions in this post:

1. For Matthew - passing a function to a field for a Sublayer's renderer was never supported. The reason for this is because MapImageLayer renderers are created server-side, so passing a JS function to the server wouldn't make sense for this particular layer, not to mention introduce security vulnerabilities. This was a documentation error on our part. I apologize for that confusion.

2. For Matthew and Aaron - Similarly, WebGL rendered feature layers also never supported functions in renderers. 

As noted by the error message, in both of those scenarios the renderer needs to be serialized at some point in our rendering pipeline. In WebGL this is required when passing information from the main thread to workers, and back to the main thread. So we didn't commit to supporting JS functions in renderers at that point.

Regarding access to additional data in Arcade - that functionality is coming. We hope to have it released in Arcade by the end of the year. That will provide you with access to other features within your layer and other layers in your map. If you need to access parameters from your application for your Arcade, you can already do this by constructing the Arcade with JavaScript then passing it to your renderer. This blog addresses one possible use case for this: https://www.esri.com/arcgis-blog/products/js-api-arcgis/mapping/generate-arcade-expressions-for-data... 

And the limitation on Sublayer saying that Arcade expressions aren't supported in renderers and popups is incorrect. I apologize again for that miscommunication in the documentation. This sample demonstrates both cases: renderer with arcade and popupTemplate with Arcade in a Sublayer: MapImageLayer - Explore data from a dynamic workspace | ArcGIS API for JavaScript 4.8 

I hope all this information helps!

Highlighted
New Contributor II

Thanks a lot for the additional info. This clarifies things for me perfectly. I will need to go back to my team to discuss how we are going to proceed from here.

Reply
0 Kudos
Highlighted
Occasional Contributor

Thanks for the detailed answer. 

Reply
0 Kudos
Highlighted
Occasional Contributor

Hello,

Sorry to come back to this answer, I was trying to setup a renderer using an Arcade Expression with javascript, following the example in your blog.

What I am trying to do, is to check if a field's value is in a list of values, return true/false and render the feature Layer using these 2 values.

I have tried multiple things but I can't make it work:

function generateArcade(ids){
   var selection = 'false'
   var value = "$feature.UID";

   for(var k in ids) {

      if(ids == value){
         selection = 'true'
      }
   }

return "IIF( '"+selection+"' == 'true','true','false')";

}
or
"IIF( "+ids.indexOf(+"$feature.UID")+ " == -1, 'in', 'out')";
etc..
then :
var valueExpressionInfo = generateArcade(ids);
var renderer = {
type: "unique-value",
valueExpression: valueExpressionInfo,
Reply
0 Kudos