Select to view content in your preferred language

Smart Mapping - Relationship Renderer 3.28 Error

1618
6
04-04-2019 02:51 AM
SabriGhaith
Emerging Contributor

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?

Robert Scheitlin, GISP

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;
});

0 Kudos
6 Replies
RobertScheitlin__GISP
MVP Emeritus

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.
  1. The main sample code you have placed outside of any widget function. Major issue.
  2. You need to add this sample code inside a widget function like startup or onOpen.
  3. You are creating a Map and trying to assign it to an element with the id of map. In WAB there is already a map and you normally never need to create a new map object you just use "this.map" inside you widget code.

There is a lot more to making a JS API sample work in WAB then just copying the code into the widget.js.

0 Kudos
SabriGhaith
Emerging Contributor

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.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Sabri,

   You still have a lot of code outside your clazz declare... Do you not see errors in your browser console?

0 Kudos
SabriGhaith
Emerging Contributor

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.

0 Kudos
SabriGhaith
Emerging Contributor

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?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

No I have no update and have not tried adding that sample as a widget myself. 

0 Kudos