Hello,
I am trying to implement this sample on my own local WAB by creating a custom widget and restructure the functions and HTML as per widget standards.
Actually i used to implement different samples, and i believe it is not about something wrong with my code.
However, when the widget opened, the user have to provide necessary inputs so the smart mapping object shall work properly as the sample in the above link.
The code code is working perfectly until it reaches to the point below:
// Creates the predominance renderer
smartMapping.createRelationshipRenderer(relationshipParams).then(this.applyRenderer);
and the console log below error:
init.js:115 "Error: smartMapping.createRelationshipRenderer: B.getClassValuesForRelationship is not a function"
Actually cannot find any documentation for getClassValuesForRelationship
Any idea why i am getting that error?
Helpful notes: The WAB i am working on is created by Portal for ArcGIS 10.6.1 and downloaded to be extended. It is hosted on IIS and the API version used in this app is 3.28 from CDN "https://js.arcgis.com".
Thanks,
define(['dojo/_base/declare',
'dojo/_base/html',
'dojo/query',
'dojo/on',
'dojo/_base/lang',
'dijit/_WidgetsInTemplateMixin',
'jimu/BaseWidget',
"dojo/_base/array",
"dojo/dom",
"dojo/number",
"esri/basemaps",
"esri/Color",
"esri/dijit/Basemap",
"esri/dijit/BasemapGallery",
"esri/layers/FeatureLayer",
"esri/map",
"esri/renderers/smartMapping",
"esri/arcgis/utils",
"esri/styles/relationship",
"esri/dijit/Legend",
"esri/dijit/PopupTemplate",
"dojo/domReady!"
],
function (declare, html, query, on, lang, _WidgetsInTemplateMixin, BaseWidget, arrayUtil, dom, number,
esriBasemaps, Color, Basemap, BasemapGallery, FeatureLayer, Map, smartMapping, utils, relationshipStyles, Legend, PopupTemplate) {
var relationshipParams;
var showDescriptiveLabelsElement;
var url = "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/ArcGIS/rest/services/Mexico_demographics/FeatureServer/0";
// Create new feature layer pointing to service with educational
// attainment data by city and assigns it a PopupTemplate
var layer = new FeatureLayer(url, {
outFields: ["NAME", "EDUC01_CY", "EDUCA_BASE", "AVGHHSZ_CY"],
infoTemplate: new PopupTemplate({
title: "{NAME}",
description: "{EDUC01_CY} people in this municipality didn't complete any formal education.",
fieldInfos: [{
fieldName: "EDUC01_CY",
label: "Population without formal education",
format: { places: 0, digitSeparator: true }
}, {
fieldName: "EDUCA_BASE",
label: "Total population"
}, {
fieldName: "AVGHHSZ_CY",
label: "Average household size"
}]
})
});
var legend = null;
function selectFields() {
relationshipParams = {
field1: {
field: "EDUC01_CY",
normalizationField: "EDUCA_BASE"
},
field2: {
field: "AVGHHSZ_CY"
},
layer: layer,
basemap: "gray",
classificationMethod: "natural-breaks",
numClasses: 3,
showOthers: false,
focus: "HH" // rotates the legend like a diamond. Set to null to make it a square
};
var schemes = relationshipStyles.getSchemes({
theme: "default",
basemap: "gray",
geometryType: "polygon",
numColors: relationshipParams.numClasses
});
addOptions(schemes);
// Creates the predominance renderer
smartMapping.createRelationshipRenderer(relationshipParams)
.then(applyRenderer);
}
function addOptions(schemes) {
var selectElem = document.getElementById("schemes");
var option = document.createElement("option");
option.value = "primary";
option.text = "primary";
selectElem.appendChild(option);
var secondarySchemes = schemes.secondarySchemes;
var primaryScheme = schemes.primaryScheme;
secondarySchemes.forEach(function (scheme, i) {
var option = document.createElement("option");
option.value = i;
option.text = "secondary " + (i + 1);
selectElem.appendChild(option);
});
selectElem.addEventListener("change", function (event) {
var selection = event.target.value;
relationshipParams.scheme = selection === "primary" ? primaryScheme : secondarySchemes[parseInt(selection)];
smartMapping.createRelationshipRenderer(relationshipParams)
.then(applyRenderer);
});
}
function applyRenderer(response) {
var renderer = changeRendererLabels(response.renderer, showDescriptiveLabelsElement.checked);
layer.setRenderer(renderer);
layer.redraw();
if (!layer.visible) {
layer.setVisibility(true);
}
legend.refresh();
}
function changeRendererLabels(renderer, showDescriptiveLabels) {
var numClasses = renderer.authoringInfo.numClasses;
var field1max = renderer.authoringInfo.field1.classBreakInfos[numClasses - 1].maxValue;
var field2max = renderer.authoringInfo.field2.classBreakInfos[numClasses - 1].maxValue;
renderer.infos.forEach(function (info) {
switch (info.value) {
case "HH":
info.label = showDescriptiveLabels ? "Large Households<br>Not formally educated" : "";
break;
case "HL":
info.label = showDescriptiveLabels ? "Small Households<br>Not much education" : Math.round(field1max * 100) + "%";
break;
case "LH":
info.label = showDescriptiveLabels ? "Large Households<br>Formally educated" : field2max;
break;
case "LL":
info.label = showDescriptiveLabels ? "Small Households<br>Not formally educated" : 0;
break;
}
});
renderer.authoringInfo.focus = showDescriptiveLabels ? "HH" : null;
return renderer;
}
var clazz = declare([BaseWidget, _WidgetsInTemplateMixin], {
baseClass: 'jimu-widget-Relationship',
_hasContent: null,
postCreate: function () {
this.inherited(arguments);
},
startup: function () {
this.inherited(arguments);
legend = new Legend({
map: this.map,
layerInfos: [{
layer: layer,
title: "Mexico Educational Attainment"
}]
}, "legendDiv");
legend.startup();
showDescriptiveLabelsElement = document.getElementById("descriptive-labels");
showDescriptiveLabelsElement.addEventListener("change", function (event) {
var renderer = changeRendererLabels(layer.renderer, showDescriptiveLabelsElement.checked);
layer.setRenderer(renderer);
layer.redraw();
legend.refresh();
});
},
onOpen: function () {
// Add the layer to the map
this.map.addLayer(layer);
selectFields();
}
});
return clazz;
});
Sabri,
You have some Major issues in your code.
Actually i used to implement different samples, and i believe it is not about something wrong with my code.
There is a lot more to making a JS API sample work in WAB then just copying the code into the widget.js.
Hi Robert,
Actually it is my bad. I copied and pasted wrong code snippets from different places while i am trying to post this question.
The code in the original post is updated now.
Sabri,
You still have a lot of code outside your clazz declare... Do you not see errors in your browser console?
No at all.
The only showstopper is the mentioned error related to the renderer.
I traced all pieces and the code is navigating as expected through all functions.
I have other widget.js structure, but that one is related to the business of my app itself, i just created this JS file to test the sample code almost as-is away from any external factors.
Hi Robert,
Do you have any update on this? Or did you try to embed the online sample into a custom widget and got working properly?
No I have no update and have not tried adding that sample as a widget myself.