POST
|
The problem here is that you're trying to highlight graphics in a FeatureLayer by assigning a new symbol to them. That would've worked in 3.x, but not in 4.x. To highlight FeatureLayer graphics in 4.x, you need to get a reference to the layer's associated FeatureLayerView, and then use its highlight method.
... View more
02-16-2024
09:19 AM
|
2
|
0
|
235
|
POST
|
This is a bug in the current version; please see this thread for further information.
... View more
02-14-2024
09:36 AM
|
0
|
0
|
97
|
POST
|
Yes, you can use a RequestInterceptor to examine the results from the server before they get delivered to the layer. In that process, you can remove any features with an invalid geometry from the array. Some other threads where this intercept-and-modify process is discussed can be found here and here.
... View more
02-07-2024
02:36 PM
|
0
|
0
|
107
|
POST
|
The value of that heading should be the same as the title property for the layer containing the graphics. If your layer doesn't have a title, that could explain it. Or, if you're not using a layer and adding your graphics directly to the MapView's graphics collection instead, that might explain it as well.
... View more
02-05-2024
02:40 PM
|
1
|
2
|
215
|
POST
|
Have you tried using the registerToken method of the IdentityManager module? I've used it to do this same kind of thing. For example: esriId.registerToken({
expires: tokenResponse.expires,
server: "https://myServer/arcgis/rest/services",
token: tokenResponse.token
});
... View more
02-05-2024
09:45 AM
|
0
|
0
|
120
|
POST
|
With the following changes I got it to highlight on mouseover: 1) Line 215 should be: const senateLayer = map.layers.items[3]; 2) Line 242 should be: highlight = layerView.highlight([newObjectId]); 3) Technically not necessary, but I also changed line 227 to: return result.graphic.layer == layerView.layer;
... View more
02-02-2024
01:49 PM
|
0
|
0
|
275
|
POST
|
You would include the id in the parameters passed to the layer's constructor, for example: var layer = new FeatureLayer({
id: "myLayerID",
url: "https://myServer/arcgis/rest/services/MyService/MapServer/0"
});
... View more
02-01-2024
03:12 PM
|
0
|
0
|
155
|
POST
|
My apologies, I sent you in the wrong direction due to a misunderstanding of the refresh event. I thought it would fire every time the layer refreshed itself, but that's not the case. Instead, the trigger we're looking for is the associated FeatureLayerView's updating property; when it changes from true to false, the layer has just finished refreshing. It is then that we should query the FeatureLayerView to see if it has any features, in which case I've also found it's best to use the view's extent (simply getting the count of the FeatureLayerView's available features can include features that aren't visible on screen). I've modified the code for the sample mentioned in the other thread, and is reproduced in its fullness below: <html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<title>Legend widget | Sample | ArcGIS Maps SDK for JavaScript 4.28</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.28/esri/themes/light/main.css" />
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
overflow: hidden;
}
</style>
<script src="https://js.arcgis.com/4.28/"></script>
<script>
function addLegendForLayer(Legend, view, container, layer) {
var childElement = document.createElement("DIV");
container.appendChild(childElement);
const legend = new Legend({
view: view,
layerInfos: [
{
layer: layer,
title: "NY Educational Attainment"
}
],
container: childElement
});
return {legend:legend,layer:layer};
}
require(["esri/views/MapView", "esri/widgets/Legend", "esri/WebMap"], (
MapView,
Legend,
WebMap
) => {
const webmap = new WebMap({
portalItem: {
// autocasts as new PortalItem()
id: "05e015c5f0314db9a487a9b46cb37eca"
}
});
const view = new MapView({
container: "viewDiv",
map: webmap
});
view.when(() => {
var container = document.createElement("DIV");
container.style.backgroundColor = "#FFFFFF";
// Add widget to the bottom right corner of the view
view.ui.add(container, "bottom-right");
addLegendForLayer(Legend, view, container, webmap.layers.getItemAt(0));
var item = addLegendForLayer(Legend, view, container, webmap.layers.getItemAt(0));
var legend2 = item.legend;
var layer2 = item.layer;
view.whenLayerView(layer2).then(function(layerView2) {
layerView2.watch("updating", function(newValue, oldValue, propertyName, target) {
if ((oldValue) && (!newValue)) {
var query = layerView2.createQuery();
query.geometry = view.extent;
layerView2.queryFeatures(query).then(function(featureSet) {
legend2.visible = (featureSet.features.length > 0);
});
}
});
});
});
});
</script>
</head>
<body class="calcite">
<div id="viewDiv"></div>
</body>
</html> To view this in action, go to the sample's sandbox, replace the code in the pane on the left with what's above (you can copy and paste), and click the "Refresh" button near the top-right of the page. After it's loaded, zoom to an area where there are no features, and the 2nd legend item disappears. Zoom back out to where there are features, and the legend reappears.
... View more
01-31-2024
09:53 AM
|
0
|
0
|
156
|
POST
|
Although this is not possible with the out of the box Legend widget, it is still possible for you to accomplish this behavior in your application, assuming the layers you're working with are client-side layers (e.g. FeatureLayers). This post shows how to use multiple Legend widgets, although having the appearance of being a single legend to the end user. If you're using FeatureLayers, you could add one Legend per layer. For each layer, you would get a reference to its associated FeatureLayerView, and then whenever it refreshes it, you would query the FeatureLayerView for its features. This query runs client-side, so is instantaneous. If it returns no features, you would hide the associated Legend instance, or if there are features returned, you would show it instead.
... View more
01-30-2024
09:39 AM
|
2
|
2
|
183
|
POST
|
I adjusted the "Intro to popups" sample to the following, which works although there's some explanation further below: <html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>Intro to popups | Sample | ArcGIS Maps SDK for JavaScript 4.28</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#instruction {
z-index: 99;
position: absolute;
top: 15px;
left: 50%;
padding: 5px;
margin-left: -175px;
height: 30px;
width: 355px;
background: rgba(25, 25, 25, 0.8);
color: white;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.28/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.28/"></script>
<script>
function adjustViewForPopup(view, popup) {
if (popup.visible) {
var contentFeatureElement = popup.container.querySelector(".esri-features__content-feature");
var headerElement = contentFeatureElement?.shadowRoot.querySelector("calcite-panel")?.shadowRoot?.querySelector("div.header-container");
if (headerElement) {
var popupRect = popup.container.getBoundingClientRect();
var viewRect = view.container.getBoundingClientRect();
var xDiff = 0, yDiff = 0;
if (popupRect.right > viewRect.right)
xDiff = (viewRect.right - popupRect.right) - 5;
else if (popupRect.left < viewRect.left)
xDiff = (viewRect.left - popupRect.left) + 5;
if (popupRect.bottom > viewRect.bottom)
yDiff = (viewRect.bottom - popupRect.bottom) - 5;
else if (popupRect.top < viewRect.top)
yDiff = (viewRect.top - popupRect.top) + 5;
if ((xDiff !== 0) || (yDiff !== 0)) {
var screenPoint = view.toScreen(view.extent.center);
view.goTo(view.toMap({x:screenPoint.x - xDiff, y:screenPoint.y - yDiff}));
}
} else
window.setTimeout(adjustViewForPopup.bind(window, view, popup), 100);
}
}
require(["esri/rest/locator", "esri/Map", "esri/views/MapView", "esri/widgets/Popup"], (locator, Map, MapView, Popup) => {
// Set up a locator url using the world geocoding service
const locatorUrl = "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer";
// Create the Map
const map = new Map({
basemap: "streets-navigation-vector"
});
var popup = new Popup();
popup.alignment = "top-center";
// Create the MapView
const view = new MapView({
container: "viewDiv",
map: map,
center: [-71.6899, 43.7598],
zoom: 12,
popup: popup
});
new MutationObserver(adjustViewForPopup.bind(window, view, popup)).observe(popup.container, {childList:true,subtree:true});
popup.watch(["content","selectedFeatureWidget"], adjustViewForPopup.bind(window, view, popup));
/*******************************************************************
* This click event sets generic content on the popup not tied to
* a layer, graphic, or popupTemplate. The location of the point is
* used as input to a reverse geocode method and the resulting
* address is printed to the popup content.
*******************************************************************/
view.popupEnabled = false;
view.on("click", (event) => {
// Get the coordinates of the click on the view
const lat = Math.round(event.mapPoint.latitude * 1000) / 1000;
const lon = Math.round(event.mapPoint.longitude * 1000) / 1000;
view.openPopup({
// Set the popup's title to the coordinates of the location
title: "Reverse geocode: [" + lon + ", " + lat + "]",
location: event.mapPoint // Set the location of the popup to the clicked location
});
const params = {
location: event.mapPoint
};
// Display the popup
// Execute a reverse geocode using the clicked location
locator
.locationToAddress(locatorUrl, params)
.then((response) => {
// If an address is successfully found, show it in the popup's content
view.popup.content = response.address;
})
.catch(() => {
// If the promise fails and no result is found, show a generic message
view.popup.content = "No address was found for this location";
});
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="instruction" class="esri-widget">Click any location on the map to see its street address</div>
</body>
</html> The main part is the function "adjustViewForPopup" added on lines 35-63. I also had to explicitly require the Popup widget on line 65, instantiate one on line 74, and assign it to the view on line 83 in order to get around an issue where it didn't fully pan on the first click. I chalk those first-click issues up to the modules being lazy loaded, coupled with the use of a shadow DOM starting in 4.28. The MutationObserver of line 86 doesn't appear to be notified when elements within a shadow root are altered, thus the additional use of "watch" two lines below it for good measure. I used a fixed alignment on line 75, because without it, the alignment will change anchors when the map is panned, thus making it seem like the panning went too far. It seems the popup's contents are fully present when the headerElement of line 40 is present, which is when the domRect has its expected values.
... View more
01-29-2024
10:45 AM
|
0
|
0
|
247
|
POST
|
If your goal is simply to keep the popup from getting cut off, you might consider the solution here. It doesn't pan the map, but instead forces to the popup to open towards the direction of the map where there's the most space.
... View more
01-26-2024
09:34 AM
|
0
|
2
|
302
|
POST
|
Ok...in this case, it seems like the client-side is doing what it should and that the problem is likely on the server-side. If you have access to ArcGIS Server Manager, you might check the logs to see if they're showing anything. Otherwise, I suppose the next course of action would be to take it up with technical support.
... View more
01-26-2024
09:31 AM
|
0
|
1
|
244
|
POST
|
I'm guessing that simply supplying the layer's tileInfo as is may not be the format expected. The aforementioned documentation doesn't give the structure of the object, and simply says "For more information on tileInfo, see the ArcGIS REST API." However, it's not clear where to go from there to find structure for the tileInfo. I'm guessing that the output is supposed to be in the format discussed here. In that case, there's a good chance that simply calling the tileInfo object's toJSON method will give you what you need.
... View more
01-25-2024
09:31 AM
|
0
|
3
|
266
|
POST
|
Version 4.26 introduced the ability to specify a background color and border for TextSymbols. See also the release notes...although it speaks specifically of FeatureLayer labels, the changes apply to any use of TextSymbol. I think that's the closest you're going to get with what the SDK natively provides.
... View more
01-24-2024
10:02 AM
|
0
|
0
|
164
|
POST
|
According to the ExportWebMap specification (search for "Syntax for WebTiledLayer"), including tileInfo for a WebTileLayer is optional, and you are correct in that the tileInfo is not included for WebTileLayers by the esri/rest/print module. I figure you have at least 2 options: 1) If you host the SDK locally, you could modify the esri/rest/print module to include the tileInfo. Within that file, the code in question looks like this for 4.28: function sa(a) {
const b = {
type: "WebTiledLayer",
urlTemplate: a.urlTemplate?.replace(/\${/g, "{"),
credits: a.copyright
};
a.subDomains && 0 < a.subDomains.length && (b.subDomains = a.subDomains);
return b
} It would be easy to insert a line between 7 and 8 that includes the tileIInfo. 2) The approach most likely to be recommended would be to use a RequestInterceptor (via esriConfig.request) to intercept the request and add the tileInfo before it gets sent to the server.
... View more
01-24-2024
09:38 AM
|
1
|
5
|
292
|
Title | Kudos | Posted |
---|---|---|
1 | 02-23-2023 03:25 PM | |
3 | 3 weeks ago | |
1 | a month ago | |
1 | 4 weeks ago | |
1 | 02-29-2024 09:53 AM |