setRenderer error getFieldsUsedInExpressions is not a function

2974
19
Jump to solution
01-29-2018 06:55 AM
AbhinavSharma
New Contributor III

Hey everyone, I am attempting to create a renderer where the user is able to select the field on which to render based off of. I need to use UniqueValueDefinition as my render which means that I cannot use RendererChooser class—Web AppBuilder for ArcGIS (Developer Edition) | ArcGIS for Developers. After selecting the field the chrome console shoots back the following error

Uncaught TypeError: a.getFieldsUsedInExpressions is not a function

My feature layer is created like so:

var landusePolygonLayer = new FeatureLayer("https://services7.arcgis.com"),
            id: "canada_Risk",//confirm works
            mode: FeatureLayer.MODE_ONDEMAND,

            outFields: ["*"]
          });‍‍‍‍‍‍

I then call getData() after the user chooses the field ( which sets currField to that field which is used in the code below.

function getData(){
            classBreaks("#ffffcc", "#006837");
          }


          function classBreaks(c1, c2) {
            var classDef = new UniqueValueDefinition();

            //define ColorRamp
            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"
            //var classField = this.get("value")
            console.log("This.get(value)", currField);//confirm the field is correct in console
            classDef.attributeField= currField;//set def field to the user selected field
            classDef.type = "classBreaksDef";


            classDef.baseSymbol = new SimpleFillSymbol("solid", null, null);
            classDef.ColorRamp = colorRamp;

            //var params = new GenerateRendererParameters();
            //params.classificationDefinition = classDef;
            console.log("here")
            this.map.getLayer("canada_Risk").setRenderer(classDef);
            console.log("here2")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
var currField
define(
  ['dojo/_base/declare',
  "dijit/_WidgetsInTemplateMixin",
  'jimu/BaseWidget',
  "esri/toolbars/draw",
  "esri/toolbars/edit",
  "esri/graphic",
  "esri/request",
  "esri/config",
  "esri/Color",
  "esri/renderers/Renderer",
  "esri/tasks/ClassBreaksDefinition",
  "esri/tasks/UniqueValueDefinition",
  "esri/tasks/ColorRamp",
  "esri/tasks/AlgorithmicColorRamp",
  "esri/tasks/GenerateRendererParameters",
  "esri/tasks/GenerateRendererTask",
  "esri/layers/LayerDrawingOptions",
  "esri/layers/FeatureLayer",
  "esri/layers/Field",
  "esri/symbols/SimpleMarkerSymbol",
  "esri/symbols/SimpleLineSymbol",
  "esri/symbols/SimpleFillSymbol",
  "esri/dijit/editing/TemplatePicker",
  "esri/dijit/editing/Editor",
  "dojo/_base/array",
  "dojo/_base/event",
  "dojo/_base/lang",
  "dojo/parser",
  "dijit/registry",
  "dojo/data/ItemFileReadStore",
  "dojox/grid/DataGrid",
  "dijit/form/FilteringSelect",
  "dijit/form/Select",
  "dojo/on",
  "dojo/data/ObjectStore",
  "dojo/store/Memory",
  "dojo/domReady!"],
  function(declare,_WidgetsInTemplateMixin, BaseWidget, Draw, Edit, Graphic, esriRequest, esriConfig, Color,Renderer,
    ClassBreaksDefinition, UniqueValueDefinition, ColorRamp, AlgorithmicColorRamp,
    GenerateRendererParameters, GenerateRendererTask, LayerDrawingOptions,
    FeatureLayer,Field,
    SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol,
    TemplatePicker,Editor,
    arrayUtils, event, lang, parser, registry, ItemFileReadStore, DataGrid, FilteringSelect,Select, On,ObjectStore, Memory) {‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Abhinav,

  So attached is a version of your widget using standard widget coding practices and it has been test, and works properly.

View solution in original post

19 Replies
RobertScheitlin__GISP
MVP Emeritus

Abhinav,

   Based on the code you posted I would say this is your issue:

          function getData(){
            lang.hitch(this, classBreaks("#ffffcc", "#006837"));
          },

You have a scope issue.

0 Kudos
AbhinavSharma
New Contributor III

Hi Robert, I ended up just removing that function entirely and hard coding the colours into my colorRamp. and calling classBreaks() as soon as a new field has been chosen and the error stays the same.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Abhinav,

   Can you provide more of your code?

0 Kudos
AbhinavSharma
New Contributor III

I will post the entire section of code:

var currField
define(
  ['dojo/_base/declare',
  "dijit/_WidgetsInTemplateMixin",
  'jimu/BaseWidget',
  "esri/toolbars/draw",
  "esri/toolbars/edit",
  "esri/graphic",
  "esri/request",
  "esri/config",
  "esri/Color",
  "esri/renderers/Renderer",
  "esri/tasks/ClassBreaksDefinition",
  "esri/tasks/UniqueValueDefinition",
  "esri/tasks/ColorRamp",
  "esri/tasks/AlgorithmicColorRamp",
  "esri/tasks/GenerateRendererParameters",
  "esri/tasks/GenerateRendererTask",
  "esri/layers/LayerDrawingOptions",
  "esri/layers/FeatureLayer",
  "esri/layers/Field",
  "esri/symbols/SimpleMarkerSymbol",
  "esri/symbols/SimpleLineSymbol",
  "esri/symbols/SimpleFillSymbol",
  "esri/dijit/editing/TemplatePicker",
  "esri/dijit/editing/Editor",
  "dojo/_base/array",
  "dojo/_base/event",
  "dojo/_base/lang",
  "dojo/parser",
  "dijit/registry",
  "dojo/data/ItemFileReadStore",
  "dojox/grid/DataGrid",
  "dijit/form/FilteringSelect",
  "dijit/form/Select",
  "dojo/on",
  "dojo/data/ObjectStore",
  "dojo/store/Memory",
  "dojo/domReady!"],
  function(declare,_WidgetsInTemplateMixin, BaseWidget, Draw, Edit, Graphic, esriRequest, esriConfig, Color,Renderer,
    ClassBreaksDefinition, UniqueValueDefinition, ColorRamp, AlgorithmicColorRamp,
    GenerateRendererParameters, GenerateRendererTask, LayerDrawingOptions,
    FeatureLayer,Field,
    SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol,
    TemplatePicker,Editor,
    arrayUtils, event, lang, parser, registry, ItemFileReadStore, DataGrid, FilteringSelect,Select, On,ObjectStore, Memory) {
      //To create a widget, you need to derive from BaseWidget.
      return declare([BaseWidget,_WidgetsInTemplateMixin], {
        // DemoWidget code goes here

        //please note that this property is be set by the framework when widget is loaded.
        //templateString: template,

        baseClass: 'jimu-widget-ROP',

        postCreate: function() {
          this.inherited(arguments);
          console.log('postCreate');
        },

        startup: function() {
          ///INICIO/////
          parser.parse();

          // refer to "Using the Proxy Page" for more information:  https://developers.arcgis.com/javascript/3/jshelp/ags_proxy.html
          esriConfig.defaults.io.proxyUrl = "/proxy/";
          map= this.map;

          map.on("layers-add-result", initEditing);


          var landusePolygonLayer = new FeatureLayer("https://services7.arcgis.cYy", {
            id: "canada_Risk",//confirm works
            mode: FeatureLayer.MODE_ONDEMAND,
            outFields: ["*"]
          });
          console.log("LayerInfo", landusePolygonLayer)
          map.addLayers([landusePolygonLayer]);

          //fieldInfo
          var canadaFields = esriRequest({
            url:"https://services7.arcgis.com//0",
            content:{
              f: "json"
            },
            callbackParamName : "callback"
          });
          console.log("fields", canadaFields)
          var fieldNames, fieldStore;
          canadaFields.then(function(resp){

            fieldNames = { identifier : "id", label: "label", items: []};
            //console.log("fields", fieldNames)
            arrayUtils.forEach(resp.fields,function(f){
              fieldNames.items.push({"id": f.name, "label": f.name});
              // console.log("f_name", f)
              //this.sourceLayerFieldSelect.set("value", f.name)
              //console.log("fieldnamesForStore", fieldNames.items)


            });
            var data = fieldNames;
            //console.log("dvfdata", data.items)

            var store = new Memory({
              data: data.items
            });

            var os = new ObjectStore({objectStore: store});
            //console.log("dsds",os)

            var s = new Select({
              store: os
            }, "sourceLayerFieldSelect");
            s.startup();
            //  this.sourceLayerFieldSelect.store(os);
            //console.log("dsddssdsd",s)

            s.on("change", function(){
              //lang.hitch(this, this.get("value"));
              console.log("my value: ", this.get("value"))
              currField = this.get("value");
              classBreaks(currField)
            })


          }, function(err){
            console.log("failed to get field names: ", err);

          });


          function classBreaks(field) {
            var classDef = new UniqueValueDefinition();

            //define ColorRamp
            var colorRamp = new AlgorithmicColorRamp();
            colorRamp.fromColor = new Color.fromHex("#ffffcc");
            colorRamp.toColor = new Color.fromHex("#006837");
            colorRamp.algorithm = "hsv"; // options are:  "cie-lab", "hsv", "lab-lch"
            //var classField = this.get("value")
            console.log("This.get(value)", field);//confirm the field is correct in console
            classDef.attributeField= field;//set def field to the user selected field
            classDef.type = "classBreaksDef";


            classDef.baseSymbol = new SimpleFillSymbol("solid", null, null);
            classDef.ColorRamp = colorRamp;

            //var params = new GenerateRendererParameters();
            //params.classificationDefinition = classDef;
            //console.log("here")
            console.log("riskCanada",this.map.getLayer("canada_Risk"))
            this.map.getLayer("canada_Risk").setRenderer(classDef);
            console.log("here2")
            //var generateRenderer = new GenerateRendererTask("https://services7.arcgis.com/0");
            //generateRenderer.execute(params, applyRenderer, errorHandler);
          }
0 Kudos
AbhinavSharma
New Contributor III

I think I might know what my problem is, I am using setRenderer for a definition and not an actual renderer. I have to change my code so that it uses an actual renderer. Do you have any idea if there is a way for me to just use myUniqueValueDefinition? 

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Abhinav,

   Here is your code with a lot of corrections. I have changed it to use standard WAB/dojo widget coding practices:

define([
  'dojo/_base/declare',
  "dijit/_WidgetsInTemplateMixin",
  'jimu/BaseWidget',
  "esri/request",
  "dojo/_base/array",
  "esri/Color",
  "esri/renderers/UniqueValueRenderer",
  "esri/tasks/AlgorithmicColorRamp",
  "esri/layers/FeatureLayer",
  "esri/symbols/SimpleFillSymbol",
  "dojo/_base/lang",
  "dijit/form/FilteringSelect",
  "dijit/form/Select",
  "dojo/on",
  "dojo/data/ObjectStore",
  "dojo/store/Memory",
  "esri/tasks/GenerateRendererParameters",
  "esri/tasks/GenerateRendererTask"
],
  function(declare, _WidgetsInTemplateMixin, BaseWidget, 
    esriRequest, arrayUtils, Color,
    UniqueValueRenderer, AlgorithmicColorRamp,
    FeatureLayer, SimpleFillSymbol,
    lang, FilteringSelect, Select, On, ObjectStore, Memory,
    GenerateRendererParameters, GenerateRendererTask) {
      //To create a widget, you need to derive from BaseWidget.
      return declare([BaseWidget, _WidgetsInTemplateMixin], {

        baseClass: 'jimu-widget-ROP',
        currField: null,

        postCreate: function() {
          this.inherited(arguments);
        },

        startup: function() {
          this.map.on("layers-add-result", initEditing);

          var landusePolygonLayer = new FeatureLayer("https://services7.arcgis.cYy", {
            id: "canada_Risk",//confirm works
            mode: FeatureLayer.MODE_ONDEMAND,
            outFields: ["*"]
          });
          
          console.log("LayerInfo", landusePolygonLayer)
          this.map.addLayers([landusePolygonLayer]);

          //fieldInfo
          var canadaFields = esriRequest({
            url:"https://services7.arcgis.com//0",
            content:{
              f: "json"
            },
            callbackParamName : "callback"
          });
          console.log("fields", canadaFields)
          var fieldNames, fieldStore;
          canadaFields.then(function(resp){
            fieldNames = { identifier : "id", label: "label", items: []};
            //console.log("fields", fieldNames)
            arrayUtils.forEach(resp.fields,function(f){
              fieldNames.items.push({"id": f.name, "label": f.name});
            });
            var data = fieldNames;

            var store = new Memory({
              data: data.items
            });

            var os = new ObjectStore({objectStore: store});

            var s = new Select({
              store: os
            }, "sourceLayerFieldSelect");
            s.startup();

            s.on("change", lang.hitch(this, function(){
              console.log("my value: ", this.get("value"))
              this.currField = this.get("value");
              lang.hitch(this, this.classBreaks(this.currField));
            }));
          }, function(err){
            console.log("failed to get field names: ", err);
          });
        },

        classBreaks: function(field){
          var generateRenderer = new GenerateRendererTask("https://services7.arcgis.cYy");
          var classDef = new UniqueValueDefinition();

          //define ColorRamp
          var colorRamp = new AlgorithmicColorRamp();
          colorRamp.fromColor = new Color.fromHex("#ffffcc");
          colorRamp.toColor = new Color.fromHex("#006837");
          colorRamp.algorithm = "hsv"; // options are:  "cie-lab", "hsv", "lab-lch"
          classDef.attributeField= field; //set def field to the user selected field
          classDef.type = "classBreaksDef";

          classDef.baseSymbol = new SimpleFillSymbol("solid", null, null);
          classDef.ColorRamp = colorRamp;

          var params = new GenerateRendererParameters();
          params.classificationDefinition = classDef; 
          
          generateRenderer.execute(params, lang.hitch(this, function(evt){
            this.map.getLayer("canada_Risk").setRenderer(evt.renderer);
          }), errorHandler);
        }
      });
    });
AbhinavSharma
New Contributor III

I was not able to apply all the cosmetic changes to the code due to a few blocks of code that i did not paste here breaking on me after making the changes. But i did add the bottom portion of your code (without the errorhandler) and now I do not get any errors in the chrome console but the layers do not render based off of the selected field.

edit1:

I got the error handler working and the error is 

Something broke, error:  Error
    at Object.k.load (init.js:1007)
    at init.js:87
    at c (init.js:103)
    at d (init.js:103)
    at b.Deferred.resolve.callback (init.js:105)
    at c (init.js:104)
    at d (init.js:103)
    at b.Deferred.resolve.callback (init.js:105)
    at init.js:92
    at h (init.js:107)
Widget.js?wab_dv=2.7:168 error:  {"code":400,"details":["Classification has missing 'classificationField' value."],"log":false,"httpCode":400,"_ssl":true}
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Abhinav,

  So attached is a version of your widget using standard widget coding practices and it has been test, and works properly.

AbhinavSharma
New Contributor III

After adding my layer urls to the widget and loading the widget onto my webapp the widget does not work. it does not give me any errors it just does not render and then when I move the map a little my layer does not load. I have attached a screenshot of the symbols as shown in the chrome console.

0 Kudos