//Updated define //
//updated last line from fields to fieldNames//
Hi everyone, I am attempting to expand my widget by adding in a renderer that is is available to the end user. I have been working my way through the following ESRI Sample. The sample is for a mapservice and not a feature layer but I do not see why the same idea can not be applied. The issue is in bold. It stops at both of those instances. I have used console.log to see if there is any difference in the object that is being passed. ( Looked at the object in the sample and compared to my own) and the only difference i can find is when i print out fieldname after the push: using (console.log("fieldnames", fieldNames)
the sample looks like this:
fieldnames
whereas from my widget it looks like this:
fieldnames
TypeError: Cannot read property 'on' of undefined
define(
['dojo/_base/declare',
'jimu/BaseWidget',
"esri/toolbars/draw",
"esri/toolbars/edit",
"esri/graphic",
"esri/request",
"esri/config",
"esri/tasks/ClassBreaksDefinition",
"esri/tasks/UniqueValueDefinition",
"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",
"dojo/_base/array",
"dojo/_base/event",
"dojo/_base/lang",
"dojo/parser",
"dijit/registry",
"dojo/data/ItemFileReadStore",
"dojox/grid/DataGrid",
"dijit/form/FilteringSelect",
"dojo/domReady!"],
function(declare, BaseWidget, Draw, Edit, Graphic, esriRequest, esriConfig,
ClassBreaksDefinition, UniqueValueDefinition, AlgorithmicColorRamp,
GenerateRendererParameters, GenerateRendererTask, LayerDrawingOptions,
FeatureLayer,Field,
SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol,
TemplatePicker,
arrayUtils, event, lang, parser, registry, ItemFileReadStore, DataGrid, FilteringSelect) {
//To create a widget, you need to derive from BaseWidget.
return declare([BaseWidget], {
// 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("MyLayer", {
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/Layer",
content:{
f: "json"
},
callbackParamName : "callback"
});
console.log("fields", canadaFields)
canadaFields.then(function(resp){
var fieldNames, fieldStore;
fieldNames = { identifier : "value", label: "name", items: []};
console.log("fields", fieldNames)
arrayUtils.forEach(resp.fields,function(f){
fieldNames.items.push({"name": f.name, "value": f.name});
console.log("fieldnames", fieldNames)
});
fieldStore = new ItemFileReadStore({ data:fieldNames});
console.log("store", fieldStore)
registry.byId("fieldNames").set("store", fieldStore);
}, function(err){
console.log("failed to get field names: ", err);
});
//update when field name changes
registry.byId("fieldNames").on("change", getData);
Solved! Go to Solution.
This works properly
Widget.html
<div>
<div data-dojo-attach-point="sourceLayerFieldSelect"></div>
</div>
Widget.js
define(['dojo/_base/declare', 'jimu/BaseWidget', 'dijit/_WidgetsInTemplateMixin', 'jimu/dijit/Message', 'dojo/on', 'dojo/_base/lang', 'dojo/store/Memory', 'dijit/form/Select', 'esri/request', 'dojo/_base/array'], function (declare, BaseWidget, _WidgetsInTemplateMixin, Message, on, lang, Memory, Select, esriRequest, arrayUtils) {
return declare([BaseWidget, _WidgetsInTemplateMixin], {
// Custom widget code goes here
baseClass: 'testing',
_featureLayer: null,
postCreate: function postCreate() {
this.inherited(arguments);
console.log('Testing::postCreate');
this._initDijits();
},
_initDijits: function _initDijits() {
var fieldNames, fieldStore, data, store, os;
var fields = esriRequest({
url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/3',
content: {
f: "json"
},
callbackParamName: 'callback'
}).then(lang.hitch(this, function (response) {
fieldNames = { identifier: 'value', label: 'name', items: [] };
arrayUtils.forEach(response.fields, function (f) {
// add some field names to the FS
fieldNames.items.push({ 'name': f.name, 'value': f.name });
});
data = fieldNames.items;
store = new Memory({
idProperty: 'name',
data: data
});
var select = new Select({
store: store,
labelAttr: 'name',
onChange: this._onFieldSelectChange
}, this.sourceLayerFieldSelect);
select.startup();
}));
},
_onFieldSelectChange: function _onFieldSelectChange(value) {
new Message({
titleLabel: 'Field Selected',
message: 'Selected ' + value
});
}
});
});
Registry is used to look for dijits in the DOM, not an object that you've declared in code. That's what's a little confusing about the Esri sample where it uses the same name for the variable and a DOM element. If you look at the body section, you'll see there is a FilteringSelect dijit with the id "fieldNames". This is what the registry is returning.
Is there a different way to grab the fields from the object? I do use the same code in my widget.html though, i assumed that the objects should be the same if they are initiated the same way. ( I just chose to omit the var=[] because I am able to call my webmap using this.map)
So you have a "fieldNames" Select (or FilteringSelect) dijit in your html code? You should probably add that module into your define.
By the way, UniqueValueDefinition and ClassBreaksDefinition are not in the same order as you call the modules in define.
My widget.html is a literal rip of the sample provided :
<label for="fieldNames">Render based on: </label>
<select id="fieldNames" name="baseSym"
data-dojo-type="dijit/form/FilteringSelect"
data-dojo-props="style:'width:200px;'">
</select>
I added the module to my define but still get the same error.
I also swapped the two definitions good catch!
What I've done in my widget is to get the element directly using this syntax. My Select dijit is defined this way in the html:
<div data-dojo-attach-point="sourceLayerFieldSelect" class="esriCTDownloadTabTextbox" data-dojo-type="dijit/form/Select"
data-dojo-props='required:true,trim:true,disabled:true'>
</div>
In my js code, I get and set the properties this way, using the attach-point id:
this.sourceLayerFieldSelect.set('value', selectedCategoryFieldValue);
And here is how to wire events:
this.own(on(this.sourceLayerFieldSelect, 'change', lang.hitch(this, this._onPrioritizationFieldSelectChange)));
What does selectedCategoryFieldValue refer to in this case? also would the second and third snippet of code replace the entire block of code:
var canadaFields = esriRequest({
url:"https://services7.arcgis.com/",
content:{
f: "json"
},
callbackParamName : "callback"
});
console.log("fields", canadaFields)
canadaFields.then(function(resp){
var fieldNames, fieldStore;
fieldNames = { identifier : "value", label: "name", items: []};
console.log("fields", fieldNames)
arrayUtils.forEach(resp.fields,function(f){
fieldNames.items.push({"name": f.name, "value": f.name});
console.log("fields_Sliced", fieldNames)
});
fieldStore = new ItemFileReadStore({ data:fieldNames});
console.log("store", fieldStore)
registry.byId("fieldNames").set("store", fieldStore);
}, function(err){
console.log("failed to get field names: ", err);
});
//update when field name changes
registry.byId("fieldNames").on("change", getData);
function getData(){
classBreaks(map.defaultFrom, map.defaultTo);
}
selectedCategoryFieldValue is a variable that is used to set the Select dijit to a specific value.
My snippets would replace practically nothing of your code. They just show how to properly create the element and to get a reference to it. The third snippet would replace
registry.byId("fieldNames").on("change", getData);
You still have to create the store and set the dijit's store, which would be something like this:
this.fieldNames.set("store", fieldStore);
When you post code, please use the Syntax Highlighter, making the code easier to read and allow us to point to a specific line number
I went ahead and made the changes but am now getting :
ReferenceError: on is not defined
from:
this.own(on(this.sourceLayerFieldSelect, 'change', lang.hitch(this, this._onPrioritizationFieldSelectChange)));
Ill attach my current code:
define(
['dojo/_base/declare',
'jimu/BaseWidget',
"esri/toolbars/draw",
"esri/toolbars/edit",
"esri/graphic",
"esri/request",
"esri/config",
"esri/tasks/ClassBreaksDefinition",
"esri/tasks/UniqueValueDefinition",
"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",
"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/domReady!"],
function(declare, BaseWidget, Draw, Edit, Graphic, esriRequest, esriConfig,
ClassBreaksDefinition, UniqueValueDefinition, AlgorithmicColorRamp,
GenerateRendererParameters, GenerateRendererTask, LayerDrawingOptions,
FeatureLayer,Field,
SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol,
TemplatePicker,
arrayUtils, event, lang, parser, registry, ItemFileReadStore, DataGrid, FilteringSelect,select) {
//To create a widget, you need to derive from BaseWidget.
return declare([BaseWidget], {
// 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/rest/", {
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.comter/0",
content:{
f: "json"
},
callbackParamName : "callback"
});
console.log("fields", canadaFields)
canadaFields.then(function(resp){
var fieldNames, fieldStore;
fieldNames = { identifier : "value", label: "name", items: []};
console.log("fields", fieldNames)
arrayUtils.forEach(resp.fields,function(f){
fieldNames.items.push({"name": f.name, "value": f.name});
console.log("fields_Sliced", fieldNames)
this.sourceLayerFieldSelect.set("value", f.name)
});
fieldStore = new ItemFileReadStore({ data:fieldNames});
console.log("store", fieldStore)
//registry.byId("fieldNames").set("store", fieldStore);
this.fieldNames.set("store", fieldStore);
}, function(err){
console.log("failed to get field names: ", err);
});
//update when field name changes
this.own(on(this.sourceLayerFieldSelect, 'change', lang.hitch(this, this._onPrioritizationFieldSelectChange)));
function getData(){
classBreaks(map.defaultFrom, map.defaultTo);
}