Reputation: 181
Very new at JavaScript and trying to build a web map using the ArcGIS API for JavaScript 4x loosely following the tutorial here: https://developers.arcgis.com/javascript/latest/sample-code/views-composite-views/index.html
I mostly wanted to keep the highlight function while allowing zooming and panning, all within a single view using my own web layers.
The error I get in the console is: Uncaught (in promise) TypeError: Cannot read property 'graphic' of undefined
I've looked at a few questions discussing similar errors, but still don't understand exactly what I mis-edited here from the tutorial code for it to throw the error. Let me know if seeing other parts of the code would be helpful. I'm banging my head against the wall here - any help would be appreciated!
Here is the highlight function code:
// highlight function
mainView
.when(maintainFixedExtent)
.then(disableNavigation)
.then(enableHighlightOnPointerMove);
function maintainFixedExtent(view) {
var fixedExtent = view.extent.clone();
view.on("resize", function () {
view.extent = fixedExtent;
});
return view;
}
let highlight = null;
let lastHighlight = null;
function enableHighlightOnPointerMove(view) {
view.whenLayerView(basinsLayer).then(function (layerView) {
view.on("pointer-move", function (event) {
view.hitTest(event).then(function (response) {
lastHighlight = highlight;
var id = null;
if (response.results.length) {
var feature = response.results.filter(function (result) {
return result.graphic.layer === basinsLayer;
})[0].graphic;
feature.popupTemplate = basinsLayer.popupTemplate;
id = feature.attributes.OBJECTID;
highlight = layerView.highlight([id]);
var selectionId = mainView.popup.selectedFeature
? mainView.popup.selectedFeature.attributes.OBJECTID
: null;
if (highlight && id !== selectionId) {
mainView.popup.open({
features: [feature]
});
}
} else {
if (mainView.popup.visible) {
mainView.popup.close();
mainView.popup.clear();
}
}
// remove the previous highlight
if (lastHighlight) {
lastHighlight.remove();
lastHighlight = null;
}
});
});
});
}
function disableNavigation(view) {
view.popup.dockEnabled = true;
view.popup.actions = [];
function stopEvtPropagation(event) {
event.stopPropagation();
}
return view;
}
Edit:
Here is a full working example using public data. I think the issue is related to me having both a point layer and a polygon layer. I only want to use the highlight function on the polygon layer, but if you hover around enough, the "uncaught (in promise) TypeError: cannot read property graphic of undefined" appears in the console and I think this is related to the point layer. Is there a workaround?
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<!--
ArcGIS API for JavaScript, https://js.arcgis.com
For more information about the views-composite-views sample, read the original sample description at developers.arcgis.com.
https://developers.arcgis.com/javascript/latest/sample-code/views-composite-views/index.html
-->
<title>Create an app with composite views - 4.15</title>
<style>
html,
body,
#mainViewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#akViewDiv {
padding: 0;
margin: 0;
height: 225px;
width: 300px;
background-color: rgba(255, 255, 255, 0.9);
}
#hiViewDiv {
padding: 0;
margin: 0;
height: 135px;
width: 200px;
background-color: rgba(255, 255, 255, 0.9);
}
</style>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.15/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.15/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/widgets/Legend"
], function(Map, MapView, FeatureLayer, Legend) {
var layer = new FeatureLayer({
portalItem: {
id: "b234a118ab6b4c91908a1cf677941702"
},
outFields: ["NAME", "STATE_NAME", "VACANT", "HSE_UNITS"],
title: "U.S. counties"
});
var layer2 = new FeatureLayer({
url: "https://services1.arcgis.com/0MSEUqKaxRlEPj5g/arcgis/rest/services/ncov_cases_US/FeatureServer/0"
});
var map = new Map({
layers: [layer, layer2]
});
var mainView = new MapView({
container: "mainViewDiv",
map: map,
popup: {
highlightEnabled: false,
dockEnabled: true,
dockOptions: {
breakpoint: false,
position: "top-right"
}
},
extent: {
xmin: -3094834,
ymin: -44986,
xmax: 2752687,
ymax: 3271654,
spatialReference: {
wkid: 5070
}
},
spatialReference: {
// NAD_1983_Contiguous_USA_Albers
wkid: 5070
},
ui: {
components: ["attribution"]
}
});
mainView.ui.add(
new Legend({
view: mainView
}),
"bottom-right"
);
mainView
.when(disablePopupOnClick)
.then(enableHighlightOnPointerMove);
let highlight = null;
let lastHighlight = null;
function enableHighlightOnPointerMove(view) {
view.whenLayerView(layer).then(function(layerView) {
view.on("pointer-move", function(event) {
view.hitTest(event).then(function(response) {
lastHighlight = highlight;
// if a feature is returned, highlight it
// and display its attributes in the popup
// if no features are returned, then close the popup
var id = null;
if (response.results.length) {
var feature = response.results.filter(function(result) {
return result.graphic.layer === layer;
})[0].graphic;
feature.popupTemplate = layer.popupTemplate;
id = feature.attributes.OBJECTID;
highlight = layerView.highlight([id]);
var selectionId = mainView.popup.selectedFeature
? mainView.popup.selectedFeature.attributes.OBJECTID
: null;
if (highlight && id !== selectionId) {
mainView.popup.open({
features: [feature]
});
}
} else {
if (mainView.popup.visible) {
mainView.popup.close();
mainView.popup.clear();
}
}
// remove the previous highlight
if (lastHighlight) {
lastHighlight.remove();
lastHighlight = null;
}
});
});
});
}
// prevents the user from opening the popup with click
function disablePopupOnClick(view) {
view.on("click", function(event) {
event.stopPropagation();
});
return view;
}
});
</script>
</head>
<body>
<div id="mainViewDiv"></div>
<div id="akViewDiv" class="esri-widget"></div>
<div id="hiViewDiv" class="esri-widget"></div>
</body>
</html>
Upvotes: 1
Views: 2870
Reputation: 5270
Example of what I think you are trying to achieve. Based on the ArcGIS example of the question, just remove everything that stop the navigation on the map, and the extra views.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>highlight features - 4.15</title>
<style>
html,
body,
#mainViewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.15/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.15/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer"
], function(Map, MapView, FeatureLayer) {
var layer = new FeatureLayer({
portalItem: {
id: "b234a118ab6b4c91908a1cf677941702"
},
outFields: ["NAME", "STATE_NAME", "VACANT", "HSE_UNITS"],
title: "U.S. counties"
});
var map = new Map({
layers: [layer]
});
var mainView = new MapView({
container: "mainViewDiv",
map: map,
popup: {
highlightEnabled: false,
dockEnabled: true,
dockOptions: {
breakpoint: false,
position: "top-right"
}
},
extent: {
xmin: -3094834,
ymin: -44986,
xmax: 2752687,
ymax: 3271654,
spatialReference: {
wkid: 5070
}
},
spatialReference: {
// NAD_1983_Contiguous_USA_Albers
wkid: 5070
},
ui: {
components: ["attribution"]
}
});
mainView
.when(disablePopupOnClick)
.then(enableHighlightOnPointerMove);
let highlight = null;
let lastHighlight = null;
function clearPopup() {
if (mainView.popup.visible) {
mainView.popup.close();
mainView.popup.clear();
}
}
function clearHighlight(lastHighlight) {
if (lastHighlight) {
lastHighlight.remove();
lastHighlight = null;
}
}
function enableHighlightOnPointerMove(view) {
view.whenLayerView(layer).then(function(layerView) {
view.on("pointer-move", function(event) {
view.hitTest(event).then(function(response) {
lastHighlight = highlight;
var id = null;
if (response.results.length) {
clearPopup();
}
var filterFeatures = response.results.filter(function(result) {
return result.graphic.layer === layer;
});
if (filterFeatures && filterFeatures.length > 0) {
var feature = filterFeatures[0].graphic;
feature.popupTemplate = layer.popupTemplate;
id = feature.attributes.OBJECTID;
highlight = layerView.highlight([id]);
var selectionId = mainView.popup.selectedFeature
? mainView.popup.selectedFeature.attributes.OBJECTID
: null;
if (highlight && id !== selectionId) {
mainView.popup.open({
features: [feature]
});
}
} else {
clearPopup();
console.log('filterFeatures is empty');
}
clearHighlight(lastHighlight);
});
});
});
}
// prevents the user from opening the popup with click
function disablePopupOnClick(view) {
view.on("click", function(event) {
event.stopPropagation();
});
return view;
}
});
</script>
</head>
<body>
<div id="mainViewDiv"></div>
</body>
</html>
Upvotes: 1