Legend load event in ArcGIS JavaScript API - arcgis-js-api

I am working on arcgis map JavaScript API and i want to show map layer legend with close icon but i am unable to find legend load event to show the same. Legend along with close icon is shown in below image.enter image description here

You can access the dom node of the legend widget after it was added to the mapview.ui with the container property of the legend widget.
This script below was taken from a sample demo
require([
"esri/views/MapView",
"esri/widgets/Legend",
"esri/WebMap"
], function(MapView, Legend, WebMap) {
var webmap = new WebMap({
portalItem: {
// autocasts as new PortalItem()
id: "4abe6a830b8f466dacf8abfde567a781"
}
});
var view = new MapView({
container: "viewDiv",
map: webmap
});
view.when(function() {
// get the first layer in the collection of operational layers in the WebMap
// when the resources in the MapView have loaded.
var featureLayer = webmap.layers.getItemAt(0);
var legend = new Legend({
view: view,
layerInfos: [
{
layer: featureLayer,
title: "NY Educational Attainment"
}
]
});
// Add widget to the bottom right corner of the view
view.ui.add(legend, "bottom-right");
//Now you can access the legend domNode and add a close button
console.log(legend.container)
});
});

Related

How can i add and remove the dynamic marker on esri map javascript api?

How can I add and remove the dynamic marker on esri map using the javascript api? When I add the marker in the graphics layer, it's added but how can I remove it and add the new marker by another latitude longitude?
This is my code so far;
require(
["esri/map",
"esri/graphic",
"esri/symbols/PictureMarkerSymbol",
"esri/symbols/TextSymbol",
"esri/geometry/Point",
"esri/SpatialReference",
"esri/tasks/ProjectParameters",
"esri/tasks/GeometryService",
"dojo/dom",
"dojo/on",
"esri/dijit/HomeButton",
"dojo/domReady!"
],
function setupmap(Map, Graphic, PictureMarkerSymbol, TextSymbol, Point, SpatialReference, ProjectParameters, GeometryService, dom, on, HomeButton) {
var map = new Map("map-container", {
center: [83.0179802, 25.32327],
zoom: 13,
basemap: "streets"
});
map.graphics.clear();
map.on("load", function (evt) {
var home = new HomeButton({map: map}, "HomeButton");
home.startup();
picSymbol = new PictureMarkerSymbol(iconType, 20, 20);
$.each(detailsJSON, function (location, lstNodes) {
var locArr = location.split("--");
var latitude=locArr[0];
var longitude=locArr[1];
var geometryPoint = new Point(longitude, latitude,new SpatialReference(4326));
map.graphics.add(new Graphic(geometryPoint, picSymbol));
});
});
}
);
You can store a reference to the Graphic object you're adding and later remove it using the remove(graphic) method.
let graphic = new Graphic(geometryPoint, picSymbol);
map.graphics.add(graphic);
...
map.graphics.remove(graphic);
You can also remove all graphics from the layer using method removeAll().
See the arcgis-js-api reference for further info.
To make your component more stateless you can use the attributes collection of the Graphic to store a tag (or an Id or similar) and remove the item based on this value.
When adding;
let graphic = new Graphic(geometryPoint, picSymbol);
graphic.attributes = { "tag": "toBeRemovedLater" };
map.graphics.add(graphic);
When removing;
angular.forEach(map.graphics.graphics, (graphic: any) => {
if (graphic.attributes && graphic.attributes.tag == "toBeRemovedLater")
map.graphics.remove(graphic);
});
You can use Sketch Widget that simplifies the process of adding and updating graphics.
const sketch = new Sketch({
availableCreateTools: ['point'],
layer: graphicsLayer,
view,
});
view.ui.add(sketch, 'top-right');

Not able to view ArcGIS non shared Scene Layer with BuildingSceneLayer even though I have signed in and the file is from my Portal

I am viewing BuildingSceneLayer using ArcGIS Javascript API.
I want to display a SceneLayer which is not shared as public in the ArcGIS portal.
When I try viewing it I get
Sceenshot
When I view in Codepen
https://codepen.io/arnofiva/pen/c410babb5384945a12b1d8206ebe27ce?editors=1010
require([
"esri/Map",
"esri/views/SceneView",
"esri/layers/BuildingSceneLayer"
], function(Map, SceneView, BuildingSceneLayer) {
// Create Map
var map = new Map({
basemap: "terrain",
ground: "world-elevation"
});
// Create the SceneView
var view = new SceneView({
container: "viewDiv",
map: map,
camera: {
position: [-74.0338, 40.6913, 707],
tilt: 81,
heading: 50
}
});
// Create SceneLayer and add to the map
var sceneLayer = new BuildingSceneLayer({
portalItem: {
id: "e7bf9f676ed64937bff9f44c84fdae2b"
},
popupEnabled: false
});
map.add(sceneLayer);
sceneLayer.when().then(function() {
view.goTo(sceneLayer.fullExtent);
});
});
I get a popup for logging in. How do I enable that in my code?

multiple markers with url

I am using Google Maps API with multiple markers & mouse over & infowindows. It works perfectly. Now I want to add an individual URL for each marker on CLICK. But for some reason, all markers always open the last URL. - What is possibly the problem?
// Define your locations: HTML content for mouseover, the info window content, latitude, longitude, url
var locations = [
['<h8>Brugg</h8>', '<h7>auseinander.</h7>', 47.4867355, 8.2109103, 'http://www.stadtereignisse.ch/dokumentiert/'],
['<h8>Aarau»</h8>', '<h7>Aarau</h7>', 47.391224, 8.038669, 'http://www.stadtereignisse.ch/erlebt/'],
['<h8>Bern</h8>', '<h7>Bern</h7>', 46.947974, 7.447447, 'http://www.stadtereignisse.ch/erwuenscht/']
];
// Add the markers and infowindows to the map
for (var i = 0; i < locations.length; i++) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][2], locations[i][3]),
/* title: locations[i][0], */
url: "http://www.stadtereignisse.ch/dokumentiert/",
map: map,
visible: true,
icon: icons[iconCounter]
});
markers.push(marker);
// CLICK (Allow each marker to have an info window)
google.maps.event.addListener(marker, 'click', function() {
window.location.href = marker.url;
});
// MOUSEOVER
google.maps.event.addListener(marker, 'mouseover', (function(marker, i) {
return function() {
infowindow.setContent(locations[i][0]);
infowindow.open(map, marker);
}
})(marker, i));
iconCounter++;
// We only have a limited number of possible icon colors, so we may have to restart the counter
if(iconCounter >= iconsLength) {
iconCounter = 0;
}
}
Look at the difference between your click handler and your mouseover handler. One of these creates a closure; the other does not. You need to create a closure for click as well.
However, instead of the complicated technique of a function-that-returns-a-function, there is a cleaner way to do it. Simply move the entire loop body into one function that you call from the loop. Then you won't need the extra complication on the mouseover (or click either).
Also, as #ValLeNain pointed out, you're setting marker.url to a hard coded value instead of a different value for each marker, so I changed that to what looks like the value you want.
Finally, a bit of user experience advice: I do not recommend opening an infowindow on a mouseover. As you have probably noticed, if you open an infowindow for a marker near the top of the visible map, the entire map shifts to bring the infowindow into view. It is confusing and surprising when a mouseover triggers that movement. Infowindows should be opened on a click, not a mouseover. Then if you want to put a link inside the infowindow text you can do that.
I didn't address this issue in the code below, but will leave it for you to sort out.
// Add the markers and infowindows to the map
for (var i = 0; i < locations.length; i++) {
addMarker( locations[i] );
}
function addMarker( location ) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(location[2], location[3]),
title: location[0],
url: location[4],
map: map,
visible: true,
icon: icons[iconCounter]
});
markers.push(marker);
// CLICK (Allow each marker to have an info window)
google.maps.event.addListener(marker, 'click', function() {
window.location.href = marker.url;
});
// MOUSEOVER
google.maps.event.addListener(marker, 'mouseover', function() {
infowindow.setContent(location[0]);
infowindow.open(map, marker);
});
iconCounter++;
// We only have a limited number of possible icon colors, so we may have to restart the counter
if(iconCounter >= iconsLength) {
iconCounter = 0;
}
}

Arcgis API for Javascript 4 Calcite map add feature layer

I am new to the ArcGIS API for Javscript 4.0 API. Using the calcite sample on the API website. Where can I add in a feature Layer to the map view and scene view? Essentially I'm trying to merge the Feature layer sample
here: https://developers.arcgis.com/javascript/latest/sample-code/layers-featurelayer/index.html
/********************
* Add feature layer
********************/
// Carbon storage of trees in Warren Wilson College.
var featureLayer = new FeatureLayer({
url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0"
});
map.add(featureLayer);
with the calcite map sample here:
https://developers.arcgis.com/javascript/latest/sample-code/frameworks-bootstrap/index.html
but am not sure what part to add the layers to. I have tried a few times. See below. Thanks
/******************************************************************
*
* Create the map and scene view and ui components
*
******************************************************************/
// Map
var map = new Map({
basemap: app.basemap
});
app.mapView = new MapView({
container: "mapViewDiv",
map: map,
center: app.center,
scale: app.scale,
padding: app.viewPadding,
popup: new Popup({
dockOptions: app.dockOptions
}),
ui: {
components: app.uiComponents
}
});
// Scene
var mapScene = new Map({
basemap: app.basemap,
ground: "world-elevation"
});
app.sceneView = new SceneView({
container: "sceneViewDiv",
map: mapScene,
center: app.center,
scale: app.scale,
padding: app.viewPadding,
popup: new Popup({
dockOptions: app.dockOptions
}),
ui: {
components: app.uiComponents
}
});
// Set the active view to scene
app.activeView = app.mapView;
// Create the search widget and add it to the navbar instead of view
app.searchWidget = new Search({
view: app.activeView
}, "searchWidgetDiv");
app.searchWidget.startup();
// IS THIS WHERE I CAN ADD LAYERS??????????????????
var featureLayer = new FeatureLayer({
url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0"
});
app.mapView.map.add(featureLayer);
app.sceneView.map.add(featureLayer);
You can add them directly to the map object in 4.0. Look at the API documentation here for a small example: https://developers.arcgis.com/javascript/latest/api-reference/esri-Map.html#layers.
Essentially it would look something like this:
var featureLayer = new FeatureLayer(url);
var map = new Map({
basemap: app.basemap,
layers: [featureLayer]
});
You would need to make sure you apply this to whichever map you want them to render on.
you may need the following code:
var countyLayer = new FeatureLayer({
url: "http://127.0.0.1:6080/arcgis/rest/services/newyourk/MapServer/1"
});
app.map.add(countyLayer);

EnhancedGrid scrolling (with large amount of data)

I'm using dojox.grid.EnhancedGrid which is created by the class MyGrid, explained below.
var MyGrid = declare(null, {
constructor: function (app, id, opts) {
this.id = id;
this.app = app;
this.core_id = app.getCoreId();
var myStore;
var jquery = {
scope: 'core',
command: 'rest',
args: {
resource: this.id,
serve: 'cooked'
},
core_id: this.core_id
};
this.jsonStore = new custom.store.JsonRest({
target: app.get_dispatcher_url(),
jquery: jquery,
// setstruct is an object to provide a method that sets a new
// grid structure as soon as data arrives.
set_structure: dojo.hitch(this, this.set_structure),
app: this.app
});
// avoid closures from holding a reference
// to jquery and preventing its GCing
jquery = null;
this.memoryStore = new Memory();
myStore = new Cache(this.jsonStore, this.memoryStore);
this.dataStore = new ObjectStore({
objectStore: myStore,
onSet: onEdited,
onNew: onEdited,
onDelete: onEdited
});
myStore = null;
// create grid
this.grid = new EnhancedGrid({
store: this.dataStore,
height: '100%',
structure: [
{ name: 'Waiting for data...', field: 'no-field', width: '10em' }
],
plugins: {
menus: { rowMenu: this._create_menu() },
nestedSorting: true,
selector: { row: 'disabled', col: 'disabled', cell: 'multi' }
}
});
// start grid
this.grid.startup();
}
});
Note that I omitted code to focus just on the creation of the "grid/store". MyGrid displays the grid on a ContentPane.
So I create an object to display the grid (with a large amount of data) and scroll to the bottom, and it will request only the visible rows properly. However, it just so happens that when I create a second grid it will request the content for the second grid and all data for the first grid!!
How can this happen? Any idea of what can be causing this?
EDITED (22/02/13):
I created a jsfiddle to demonstrate the problem I'm getting: see jsfiddle
How to reproduce the problem:
Click on New Tab button, open the console and check how many rows were fetched.
Go to the bottom of the grid (quickly) and check the console again.
Click on New Tab again, go to the console and you can see that all rows, not loaded yet, from previous grid were fetched.
Note: I found out that this only happens on Google Chrome. I tested with Firefox and everything worked well.