Breaking change in 4.14, smartmapping

2409
20
01-03-2020 08:16 AM
DavidChevrier
Occasional Contributor II

Hi,

  I have a website that allows users to select a species of fish and map it.  It uses the javascript api and php to connect to oracle and retrieve the data.  I symbolize that data as points with a gradient color based on the number of individuals caught at that station and the size of the point based on the total weight of that species at that station.  Because the max/min for both variables is widely different between species, I use the smartmapping tools to generate the breaks on the fly.  While I know this isn't the best practice, its the best solution I could come up with, since universal break points won't work. 

 

It works fine in 4.13 and prior, but fails in 4.14.  The error message in the developer tools of chrome and firefox is "d {name: "feature-layer-adapter:insufficient-data", message: "No features are available to calculate statistics", details: undefined}"

 

I'm able to display the data in 4.14 with a single symbol with no problems.  However, when I use any smartmapping tools, it fails.  Even if I just try to symbolize with one property (like just a color ramp based on the number of species caught, and ignore the weight component) it fails with the same error. 

 

I'm looking for advice to make this work in the latest version of your api.  Also, I have not tried this in 2D, it is in a 3D view.

 

Here is the code in question:

currentClassification = "natural-breaks";

var sizeParams = {
  layer: speciesLayer,
  view: view3D,
  field: "CatchWtCal",
  classificationMethod: currentClassification,
  numClasses: 5
};

var colorParams = {
  layer: speciesLayer,
  view: view3D,
  field: "CatchNoCal",
  classificationMethod: currentClassification,
  numClasses: 5
};

sizeRendererCreator.createVisualVariables(sizeParams)
.then(function (response) {
  var sizeVVs = response.visualVariables;
  colorRendererCreator.createClassBreaksRenderer(colorParams)
  .then(function (response1) {
    var colorRend = response1.renderer;
    colorRend.visualVariables = sizeVVs;
    speciesLayer.renderer = colorRend;

    if (!map.layers.includes(speciesLayer)) {
      map.add(speciesLayer);
      filterData();
    }
  })
}).catch(function (error) {
  console.error(error)
});
0 Kudos
20 Replies
KristianEkenes
Esri Regular Contributor

Hey David,

I'm not able to reproduce this. Are you able to share a codepen that demonstrates your issue? I used the same code as above, but with a different layer and field, And I got an expected result.

While I know this isn't the best practice, its the best solution I could come up with, since universal break points won't work.

Regarding this point. The doc that says to avoid using it if possible is specifically referring to using smart mapping functions as a lazy way of setting renderers on layers. If you know exactly how the layer should be rendered (e.g. colors, breaks, etc), then just set it on the layer or save it to the service. 

Your use case seems like a totally valid reason for using these methods.

0 Kudos
KristianEkenes
Esri Regular Contributor
0 Kudos
DavidChevrier
Occasional Contributor II

Thanks.  Maybe it is how I am creating the feature layer, but I do get it to work by switch to 4.13.  In your sample, I don't have access to the csv you create the layer with, so I don't see any points on codepen.  Here is the code I use to create the featurelayer, since I can't do a codepen that hits my oracle database.  Do you see anything that would prevent the smartmapping from happening here: 

Thanks

var oReq = new XMLHttpRequest();
  oReq.onreadystatechange = function () {
    if (oReq.readyState == 4 && oReq.status == 200) {
      var speciesData = oReq.responseText;
      var lines = speciesData.split("\n");
      for (var i = 0; i < (lines.length - 1); i++) {
        var receivedData = lines[i].split(",");
        var newPoint = new Graphic({
          geometry: new Point({
            longitude: Number(receivedData[0]),
            latitude: Number(receivedData[1])
           }),
           attributes: {
             ObjectID: i,
             Depth: Number(receivedData[2]),
             CatchNoCal: Number(receivedData[3]),
             CatchWtCal: Number(receivedData[4]),
             Season: receivedData[5],
             Year: Number(receivedData[7])
          }
        });
        allFeatures.push(newPoint);
      }

      createSpeciesRenderer();

    }
  }
  oReq.open("GET", "retrieveSpeciesData.php?svspp=" + currentSVSPP, true);
  oReq.send();
}


function createSpeciesRenderer() {
  map.remove(speciesLayer);

  speciesLayer = new FeatureLayer({
    source: allFeatures,
    fields: fields,
    id: "SpeciesFeatureLayer",
    objectIdField: "ObjectID",
    spatialReference: {
      wkid: 102100
    },
    geometryType: "point",
    popupTemplate: pTemplate,
    visible: true
  });

  var sizeParams = {
    layer: speciesLayer,
    view: view3D,
    field: "CatchWtCal",
    classificationMethod: currentClassification,
    numClasses: 5
  };

  var colorParams = {
    layer: speciesLayer,
    view: view3D,
    field: "CatchNoCal",
    classificationMethod: currentClassification,
    numClasses: 5
  };

  sizeRendererCreator.createVisualVariables(sizeParams)
    .then(function (response) {
      var sizeVVs = response.visualVariables;
      colorRendererCreator.createClassBreaksRenderer(colorParams)
        .then(function (response1) {
          var colorRend = response1.renderer;
          colorRend.visualVariables = sizeVVs;
          speciesLayer.renderer = colorRend;

          if (!map.layers.includes(speciesLayer)) {
            map.add(speciesLayer);
          }
        })
  }).catch(function (error) {
    console.error(error)
  });
}
0 Kudos
KristianEkenes
Esri Regular Contributor

Sorry. I was using an internal link. I updated it to a service you should see now. I'm looking at your code now.

0 Kudos
KristianEkenes
Esri Regular Contributor

Try adding the layer to the map before calling the functions. It might not be able to get statistics from the view otherwise. 

I know the doc shows adding the layer after generating the renderer, but I wonder if that doesn't work for client-side layers at 4.14.

0 Kudos
DavidChevrier
Occasional Contributor II

Hi,

   I just tried that and unfortunately, that doesn't work.  It will load the featurelayer fine.  It only fails when I try to create and apply this smartmapping renderer.  I can get the points to load with a default simple symbol no problem, so it definitely is related to the renderer.  I am also not able to get statistics on the layer when creating the renderer.

0 Kudos
KristianEkenes
Esri Regular Contributor

FYI, we're still looking into this.

DavidChevrier
Occasional Contributor II

Excellent, glad to know.  Its working fine with 4.13 and I'm continuing to develop with that version.  Let me know if you need any additional code or information

0 Kudos
KristianEkenes
Esri Regular Contributor

We fixed a bug that sounds very similar to this one. Can you try your app using our dev build? https://js.arcgis.com/next 

0 Kudos