I need to combine my JSON file to an existing featureLayer, adding additional attributes that I want to use to render my polygons. I'm using the example https://developers.arcgis.com/javascript/jssamples/data_gas_prices.html I have stepped through my graphics and at the end of that looping, my featureLayer has the new attributes I need. That example is calculating the class breaks manually, but I'd like to use the generateRendererTask instead.
I know I am getting lost in the order of the events. Once I have the new attributes I want to use one of them as the classification field for the renderer. In the functions that I define it, it doesn't yet recognize that attribute as being available. Putting my breakpoints in right after I've looped through the graphics, I believe that it's there. I'm not calling the render functions correctly, or I need to have an event listener set up for the featureLayer. In the original example, there is an update-end listener on the featureLayer. I"m not sure what that's for. I have moved my call to generateClassBreaks to different positions, but I continue to get the error that it can't find my classification field "CROP", which is one of the attributes I introduced from the JSON file.
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title></title>
<link rel="stylesheet" href="http://js.arcgis.com/3.10/js/esri/css/esri.css">
<link rel="stylesheet" href="css/style.css">
<script type="text/javascript" >var dojoConfig = {
parseOnLoad: false,
async:true,
packages: [{
name: "extras",
location: location.pathname.replace(/\/[^/]+$/, "") + "/extras"
}]
};
</script>
<script type="text/javascript" src="http://js.arcgis.com/3.10/"></script>
<script type="text/javascript" >
var pathName = "https://myserverURL";
var defaultFrom = "#feedde";
var defaultTo = "#e75303";
var interval = 5; //used to generate renderer
require([
"dojo/parser", "dojo/json", "dojo/_base/array", "dojo/_base/connect", "esri/Color",
"dojo/number", "dojo/dom-construct",
"esri/map", "esri/geometry/Extent","esri/SpatialReference", "esri/symbols/SimpleLineSymbol",
"esri/symbols/SimpleFillSymbol", "esri/renderers/SimpleRenderer", "esri/renderers/ClassBreaksRenderer",
"esri/layers/FeatureLayer", "esri/dijit/Legend", "esri/request", "extras/Tip",
"esri/tasks/ClassBreaksDefinition", "esri/tasks/AlgorithmicColorRamp",
"esri/tasks/GenerateRendererParameters", "esri/tasks/GenerateRendererTask",
"esri/layers/LayerDrawingOptions",
"dijit/layout/BorderContainer", "dijit/layout/ContentPane", "dojo/domReady!"
], function(
parser, JSON, arrayUtils, conn, Color, number, domConstruct,
Map, Extent, SpatialReference, SimpleLineSymbol, SimpleFillSymbol, SimpleRenderer, ClassBreaksRenderer,
FeatureLayer, Legend, esriRequest, Tip,
ClassBreaksDefinition, AlgorithmicColorRamp,GenerateRendererParameters, GenerateRendererTask, LayerDrawingOptions) {
parser.parse();
spatialReference = new SpatialReference({wkid: 102100 });
var startExtent = new Extent(-10583000, 4287025, -9979000, 4980462, spatialReference);
map = new Map("map", {
extent: startExtent
});
var defaultSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([182, 182, 182]), 1), new Color([190, 190, 190, 0.7]))
var template = "<strong>${COUNTYNAME}";
tip = new Tip({
"format": template,
"node": "legend"
});
featureLayer = new FeatureLayer(pathName+"/arcgis/rest/services/BaseMap/county_simple/MapServer/0", {
maxAllowableOffset: map.extent.getWidth() / map.width,
mode: FeatureLayer.MODE_SNAPSHOT,
outFields: ["COUNTYNAME"],
visible: true
});
featureLayer.setRenderer(new SimpleRenderer(null));//starts empty
var updateEnd = featureLayer.on("update-end", function() {
updateEnd.remove();
var def = esriRequest({
// url: "http://apify.heroku.com/api/aaagasprices.json",
url: "../json/agChemical2.json",
callbackParamName: "callback"
});
def.then(drawFeatureLayer, drawFeatureError);
generateClassBreaks(defaultFrom, defaultTo);
// wire up the tip
featureLayer.on("mouse-over", tip.showInfo);
featureLayer.on("mouse-out", tip.hideInfo);
});
map.addLayer(featureLayer);
function drawFeatureLayer(data) {
var values = (typeof data === "string" ) ? JSON.parse(data) : data;
arrayUtils.forEach(featureLayer.graphics, function(graphic) {
var rec = values[graphic.attributes.COUNTYNAME];
if (rec) {
var recData = rec[0];
var atts = [];
for(var att in recData){
atts.push(att);
var field = att;
// console.log ('att = ' + att + ", value = " + recData[att]);
graphic.attributes[att] = recData[att];
}
}
});
domConstruct.destroy("loading");
}
//functions for generating symbology for the layer selected
function generateClassBreaks(c1, c2) {
var classDef = new ClassBreaksDefinition();
classDef.classificationField = "CROP";
classDef.classificationMethod = "quantile";
classDef.breakCount = interval; //defined as 5
var colorRamp = new AlgorithmicColorRamp();
colorRamp.fromColor = new Color.fromHex(c1);
colorRamp.toColor = new Color.fromHex(c2);
colorRamp.algorithm = "hsv"; // options are: "cie-lab", "hsv", "lab-lch"
classDef.baseSymbol = defaultSymbol;
classDef.colorRamp = colorRamp;
var params = new GenerateRendererParameters();
params.classificationDefinition = classDef;
// params.precision = 2;
// params.formatLabel = true;
// var clauseInput = classDef.classificationField;
// params.where= clauseInput + " > 0";
var generateRenderer = new GenerateRendererTask(featureLayer);
generateRenderer.on("error", taskErrorHandler);
generateRenderer.execute(params, applyRenderer);
}
function applyRenderer(renderer) {
var optionsArray = [];
renderer.defaultSymbol = defaultSymbol;
var drawingOptions = new LayerDrawingOptions();
drawingOptions.renderer = renderer;
optionsArray[0] = drawingOptions;
agLayer.setLayerDrawingOptions(optionsArray);
featureLayer.redraw();
// getInfoFromRender(renderer);//creates arrays the legend will use
// createLegend();
}
function taskErrorHandler(err){
console.log("error in task is " + err.error);
}
// function used by the class breaks renderer to get the
// value used to symbolize each state
function findBreakValue(graphic) {
ntyValues[COUNTY];
}
function calcBreaks(min, max, numberOfClasses) {
var range = (max - min) / numberOfClasses;
var breakValues = [];
for ( var i = 0; i < numberOfClasses; i++ ) {
breakValues = formatNumber(min + ( range * i ));
}
// console.log("break values: ", breakValues);
return breakValues;
}
function formatNumber(num) {
return number.format(num, { "places": 2 });
}
function drawFeatureError(e) {
console.log("error getting data: ", e);
}
}
);
</script>
</head>
<body>
<div id="loading" class="shadow loading">
Getting Data...
<img src="http://dl.dropbox.com/u/2654618/loading_gray_circle.gif" alt="loading image">
</div>
<div id="legend" class="shadow info"></div>
<div data-dojo-type="dijit.layout.BorderContainer"
data-dojo-props="design:'headline',gutters:false"
style="width: 100%; height: 100%; margin: 0;">
<div id="map"
data-dojo-type="dijit.layout.ContentPane"
data-dojo-props="region:'center'">
<div id="title" class="shadow info">Current Values by County</div>
</div>
</div>
</body>
</html>
Now that I look at this more closely, only the graphics within the featureLayer have the new attributes. That isn't something that percolates back to featureLayer.fields. Since generateRendererParameters is looking for a field, it is failing.
Is there a workaround to this? It seems like a lot of work to create a FeatureCollection instead just so I have the fields for the task. Maybe I should just go back to the original gas price mash up and generate the breaks manually.
I have created a custom geoprocessing service. It is creating a frequency table by Frequency tool and exporting target feature class to scratch.gdb and add frequency column to temp feature class. Then it creates a map service layer from result. Then I am using generate renderer from result map service.
But i have also one problem with renderer. I am using uniqueValueDef with color ramp. I want to order colors according to frequency values but it does not. classBreaksDef is ordering but it is not genereting symbology for null values. I'am still looking for solution.