Enable arcgis API JS popups with Vue CLI 3 - vue.js

I am trying to get popups from the ArcGIS API JS to display using the framework Vue-CLI 3.
But even with a simple sample code, I cannot make it work: Here is the code in vanilla JS:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>Popup actions | Sample | ArcGIS API for JavaScript 4.17</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.17/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.17/"></script>
<script>
require([
"esri/Map",
"esri/layers/FeatureLayer",
"esri/views/MapView",
"esri/geometry/geometryEngine"
], function (Map, FeatureLayer, MapView, geometryEngine) {
// Create the Map
var map = new Map({
basemap: "gray-vector"
});
// Create the MapView
var view = new MapView({
container: "viewDiv",
map: map,
center: [-117.08, 34.1],
zoom: 11
});
var template = {
// autocasts as new PopupTemplate()
title: "Trail run",
content: "{name}",
};
var featureLayer = new FeatureLayer({
url:
"https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/TrailRuns/FeatureServer/0",
outFields: ["*"],
popupTemplate: template,
});
map.add(featureLayer);
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
As you can see, when clicking a feature, a popup appears.
If I try to implement this in my vue-CLI project I can not make it work. When clicking on the a feature, it will highlight, but nothing will open. Here is my code .vue:
<template>
<div></div>
</template>
<script>
import { loadModules } from "esri-loader";
export default {
name: "web-map",
mounted() {
// lazy load the required ArcGIS API for JavaScript modules and CSS
loadModules([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
]).then(([ArcGISMap, MapView, FeatureLayer]) => {
const map = new ArcGISMap({
basemap: "topo-vector",
});
this.view = new MapView({
container: this.$el,
map: map,
center: [-117.08, 34.1],
zoom: 11,
});
var template = {
// autocasts as new PopupTemplate()
title: "Trail run",
content: "{name}",
};
var featureLayer = new FeatureLayer({
url:
"https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/TrailRuns/FeatureServer/0",
outFields: ["*"],
popupTemplate: template,
});
map.add(featureLayer);
});
},
beforeDestroy() {
if (this.view) {
// destroy the map view
this.view.destroy();
}
},
};
</script>
<style scoped>
div {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
</style>
Am I missing something? (I followed arcgis api js tutorial to get it work in vue-cli -https://developers.arcgis.com/javascript/latest/guide/vue/ )
Thank you very much for your help!
Julien

Your code is fine, you are just not adding css. You are missing { css: true }, that's all.
loadModules(
["esri/Map", "esri/views/MapView", "esri/layers/FeatureLayer"],
{ css: true } // <-- HERE
).then(([ArcGISMap, MapView, FeatureLayer]) => {
//...
}
HERE code with the fix.

Related

Search and Zoom in to a location

I am plotting some text graphics on a graphics layer and now I need to give an option on the map to search for a specific text and navigate to that location and zoom in.
Can someone please guide me with the approach?
Here is the sample code where if I search for 560001, the map should be zoom in to that location.
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.22/esri/themes/light/main.css">
<script src="https://js.arcgis.com/4.22/"></script>
<script>
require([
"esri/WebMap",
"esri/views/MapView",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/symbols/TextSymbol"
], function (WebMap, MapView, Graphic, GraphicsLayer, TextSymbol) {
const webmap = new WebMap({
portalItem: {
id: "36f72c8a71b542399ca09e10c5aa55f4"
}
});
const view = new MapView({
container: "viewDiv",
map: webmap,
center: [-37.731338217717074, 175.22263172713014],
zoom: 10
});
this.objectTypeList = [
{ Location: '560001', latitude: -37.731338217717074, longitude: 175.22263172713014 },
{ Location: '560002', latitude: -37.487705856583744, longitude: 175.09324140306873 },
{ Location: '560003', latitude: -37.505917118655056, longitude: 175.12036900524583 },
{ Location: '560005', latitude: -37.67287982024181, longitude: 175.23882277753953 },
{ Location: '560005', latitude: -37.67310492511848, longitude: 175.23890380457217 }
];
var graphicsLayer = new GraphicsLayer();
webmap.layers.add(graphicsLayer);
this.objectTypeList.forEach(item => {
var point = {
type: "point",
longitude: item.longitude,
latitude: item.latitude
};
var textSymbol = new TextSymbol({
color: "#BB0000",
haloColor: "black",
haloSize: "1px",
text: `${item.Location}`,
font: { size: 12, family: "Josefin Slab", weight: "bold" }
});
var pointGraphic = new Graphic({
geometry: point,
symbol: textSymbol
});
graphicsLayer.add(pointGraphic);
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
You just need to find the selected (somehow) location in the graphics of GraphicLayer using the symbol text property.
Now, you are using geographic (lon, lat) to create the geometries but your map is in another spatial reference system. In that order to zoom to the geometries you will have to project them.
Take a look a the example I put for you, I use a simple select to choose the graphic, and I use a on client projection method, another option would be server side projection.
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.22/esri/themes/light/main.css">
<script src="https://js.arcgis.com/4.22/"></script>
<script>
require([
"esri/WebMap",
"esri/views/MapView",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/symbols/TextSymbol",
"esri/geometry/SpatialReference",
"esri/geometry/projection"
], function (WebMap, MapView, Graphic, GraphicsLayer, TextSymbol, SpatialReference, projection) {
const webmap = new WebMap({
portalItem: {
id: "36f72c8a71b542399ca09e10c5aa55f4"
}
});
const view = new MapView({
container: "viewDiv",
map: webmap,
center: [-37.731338217717074, 175.22263172713014],
zoom: 10
});
this.objectTypeList = [
{ Location: '560001', latitude: -37.731338217717074, longitude: 175.22263172713014 },
{ Location: '560002', latitude: -37.487705856583744, longitude: 175.09324140306873 },
{ Location: '560003', latitude: -37.505917118655056, longitude: 175.12036900524583 },
{ Location: '560004', latitude: -37.67287982024181, longitude: 175.23882277753953 },
{ Location: '560005', latitude: -37.67310492511848, longitude: 175.23890380457217 }
];
var graphicsLayer = new GraphicsLayer();
webmap.layers.add(graphicsLayer);
this.objectTypeList.forEach(item => {
var point = {
type: "point",
longitude: item.longitude,
latitude: item.latitude
};
var textSymbol = new TextSymbol({
color: "#BB0000",
haloColor: "black",
haloSize: "1px",
text: `${item.Location}`,
font: { size: 12, family: "Josefin Slab", weight: "bold" }
});
var pointGraphic = new Graphic({
geometry: point,
symbol: textSymbol
});
graphicsLayer.add(pointGraphic);
});
projection.load().then(function() {
const outSR = new SpatialReference({wkid: 2193});
const dic = {};
graphicsLayer.graphics.forEach(g => dic[g.symbol.text] = projection.project(g.geometry, outSR));
view.when(function(){
const locationZoomButton = document.getElementById("locationZoomButton");
locationZoomButton.addEventListener("click", function(){
const locationSelect = document.getElementById("locationSelect");
const locationText = locationSelect.value;
if (dic.hasOwnProperty(locationText)) {
view.goTo(dic[locationText]);
}
});
});
});
});
</script>
</head>
<body>
<div>
<select id="locationSelect">
<option value="560001">560001</option>
<option value="560002">560002</option>
<option value="560003">560003</option>
<option value="560004">560004</option>
<option value="560005">560005</option>
</select>
<button id="locationZoomButton"> Zoom </button>
</div>
<div id="viewDiv"></div>
</body>
</html>

My html code can't reach my vue component

This is my second day with vue. I was already using webpack and vue-cli, but I would like to understand how to make everything working within one file. I developed a code which works well, but I would like to refactor the code to have a component which I could later use to generate screen full of color changing tiles.
I tried Vue.component('name', {}), but with no result, because in the console I'm seeing [Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions. and [Vue warn]: Unknown custom element: <brick> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
This code works well:
<html>
<head>
<title>v pavle</title>
<script type="text/javascript" src="https://vuejs.org/js/vue.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
template:
'<div v-bind:style="styleobj" v-on:mouseover="changebgcolor" v-on:mouseout="changebgcolor"></div>',
data: {
styleobj: {
width: "100px",
height: "100px",
backgroundColor: "white"
}
},
methods: {
changebgcolor: function() {
this.styleobj.backgroundColor = Math.floor(
Math.random() * 16777215
).toString(16);
}
}
});
</script>
</body>
</html>
And that code gives everything, but not what I want to see :(
<html>
<head>
<title>v pavle</title>
<script type="text/javascript" src="https://vuejs.org/js/vue.js"></script>
</head>
<body>
<div id="app">
<brick></brick>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#app"
});
var brick = Vue.component("brick", {
template:
'<div v-bind:style="styleobj" v-on:mouseover="changebgcolor" v-on:mouseout="changebgcolor"></div>',
data: {
styleobj: {
width: "100px",
height: "100px",
backgroundColor: "white"
}
},
methods: {
changebgcolor: function() {
this.styleobj.backgroundColor = Math.floor(
Math.random() * 16777215
).toString(16);
}
}
});
</script>
</body>
</html>
It may seem easy for you, but after 7h spent, there is nothing more for me, but just ask you on SO
Okay I will answer your 2 questions. First and about data, it has to be a function. So you have to write it like that:
data() {
return {
styleobj: {
width: "100px",
height: "100px",
backgroundColor: "white"
}
}
}
After that, your forgot to reference your component in your Vue instance. Try that:
var vm = new Vue({
el: "#app",
components: {
brick: brick
}
})
Hope it will work.
Data must be a function like data: function(){ return obj }
Register the component using components: {yourcomponent}
You needed to use # in front of your color.
<html>
<head>
<title>v pavle</title>
<script type="text/javascript" src="https://vuejs.org/js/vue.js"></script>
</head>
<body>
<div id="app">
Hello App!
<brick>Hello Brick</brick>
</div>
<script type="text/javascript">
var brick = Vue.component("brick", {
template:
'<div :style="styl" #click="changebgcolor" #mouseover="changebgcolor" #mouseout="changebgcolor"><slot></slot></div>',
data: function(){
return {
styl: {
width: "100px",
height: "100px",
backgroundColor: "#b6d8a1",
color: "blue"
}
};
},
methods: {
changebgcolor: function() {
console.log('changebgcolor!');
this.styl.backgroundColor = "#"+ Math.floor(
Math.random() * 16777215
).toString(16);
}
}
});
var vm = new Vue({
el: "#app",
components:{brick:brick}
});
</script>
</body>
</html>
When using Vue.component, you need to make sure that you have registered all components once you start rendering your app. At the moment, you first render the main app and then register the component, so swap those around
var brick = Vue.component("brick", {
template:
'<div v-bind:style="styleobj" v-on:mouseover="changebgcolor" v-on:mouseout="changebgcolor"></div>',
data: {
styleobj: {
width: "100px",
height: "100px",
backgroundColor: "white"
}
},
methods: {
changebgcolor: function() {
this.styleobj.backgroundColor = Math.floor(
Math.random() * 16777215
).toString(16);
}
}
});
var vm = new Vue({
el: "#app"
});
The data property on your component should be a function that returns an object. Why? Because otherwise all instances of your component share the same data, meaning all tiles on your app would have the same color.
data() {
return {
styleobj: {
width: "100px",
height: "100px",
backgroundColor: "white"
}
}
},
You should first register the component before you fire up the Vue instance, just reorder your code and it works!

get feature layer on button click

how to get a feature layer on button click and display.
S_layer = new FeatureLayer("http://localhost:6080/arcgis/rest/services/...../MapServer/0",{
mode: FeatureLayer.MODE_SELECTION,
outFields: ["*"]
});
map.addLayer(S_layer);
function soil()
{
queryTask = new esri.tasks.QueryTask("http://localhost:6080/arcgis/rest/services/...../MapServer/0");
var query = new esri.tasks.Query();
query.returnGeometry = true;
query.outFields = ["soil"];
var name = document.getElementById("combo1").value.toString();
query.where = "NAME = '" + name;
<!-- queryTask.execute(query); -->
S_layer.selectFeatures(query, queryTask.SELECTION_NEW, function (features) {
if(features[0]){
thePoly = features[0].geometry;
theExtent = thePoly.getExtent().expand(1.8); //Zoom out slightly from the polygon's extent
map.setExtent(theExtent);
}
});
}
<button type="button" id="btn" class = "button" class="btn-default" onclick = soil(); >Soil</button>
<br></br>
but this query does not run it gives error of "init.js:89 Error: Unable to complete operation.
at Object.g.load".
As I understood, you want to add a layer on button click.
Below is the code for this:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Hydrography - Selection mode</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.21/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.21/esri/css/esri.css">
<style>
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
body {
background-color: white;
overflow: hidden;
font-family: sans-serif;
}
</style>
</head>
<body class="claro">
<br>
Add layers-
<button type="button" id="addWaterBodies" class = "button" >water Bodies</button>
<button type="button" id="addRivers" class = "button" >River</button> <br> <br>
<div id="map" >
</div>
<script src="https://js.arcgis.com/3.21/"></script>
<script>
var map;
require([
"esri/map",
"esri/dijit/editing/Editor", "esri/dijit/editing/TemplatePicker",
"esri/tasks/GeometryService",
"esri/layers/ArcGISDynamicMapServiceLayer", "esri/layers/FeatureLayer",
"dojo/i18n!esri/nls/jsapi", "esri/config",
"dojo/_base/array", "dojo/keys", "dojo/parser",
"dijit/layout/BorderContainer", "dijit/layout/ContentPane",
"dojo/domReady!"
], function(
Map,
Editor, TemplatePicker,
GeometryService,
ArcGISDynamicMapServiceLayer, FeatureLayer,
esriBundle, esriConfig,
arrayUtils, keys, parser
) {
parser.parse();
map = new Map("map", {
basemap: "hybrid",
center: [-96.325, 37.855],
zoom: 13
});
map.infoWindow.resize(400,300);
function addWaterBodies(){
var waterBodiesLayer= map.getLayer("waterLayerId");
if(!waterBodiesLayer){
waterBodiesLayer = new FeatureLayer("https://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydrography/Watershed173811/FeatureServer/0", {
id : "waterLayerId",
outFields: ["*"],
});
map.addLayer(waterBodiesLayer);
} else {
alert("water bodies layer already added");
}
}
function addRivers(){
var riversLayer= map.getLayer("riverLayerId");
if(!riversLayer){
riversLayer = new FeatureLayer("https://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydrography/Watershed173811/FeatureServer/1", {
id:"riverLayerId",
outFields: ["*"]
});
map.addLayer( riversLayer);
} else {
alert("River layer already added");
}
}
document.getElementById("addWaterBodies").onclick = addWaterBodies;
document.getElementById("addRivers").onclick = addRivers;
});
</script>
</body>
</html>

onclick event for marker is not working in openlayer3 on changing the size of the div

i am plotting the markers on the map in openlayer3 as shown below
<!DOCTYPE html>
<html>
<head>
<title>Rotation example</title>
<link rel="stylesheet" href="http://openlayers.org/en/v3.0.0/css/ol.css" type="text/css">
<script src="http://openlayers.org/en/v3.11.2/build/ol.js"></script>
</head>
<body>
<div id="map" style="width:1000px;height:1000px"></div>
<script>
var map;
function initMap() {
map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: ({
collapsible: false,
})
}),
view: new ol.View({
center: ol.proj.fromLonLat([103.986908, 1.353199]),
rotation: 68*Math.PI/180,
zoom: 18
})
});
}
function invokeAddMarker(){
var markerData = [
{
"title": 'point1',
"lat": 1.350664,
"lng": 103.985190,
"description": 'yyyy'
}, {
"title": 'point2',
"lat":1.353604,
"lng": 103.986395,
"description": 'zzz'
}, {
"title": 'point3',
"lat": 1.357227,
"lng": 103.9879999,
"description": 'uuu'
}
];
for(var i=0;i<markerData.length;i++){
addmarker(markerData[i].lat,markerData[i].lng);
}
}
function addmarker(lat,lng){
console.log("*****lat******"+lat);
console.log("*****lng******"+lng);
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.transform([lng,lat],'EPSG:4326', 'EPSG:3857')),
name: 'camera'
});
var iconStyle = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
opacity: 0.75,
src: 'camera.png'
}))
});
iconFeature.setStyle(iconStyle);
vectorSource = new ol.source.Vector({
features: [iconFeature]
});
/*t clear the markers*/
/*vectorSource.clear();*/
vectorLayer = new ol.layer.Vector({
source: vectorSource
});
map.addLayer(vectorLayer);
map.on('click', function(evt) {
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature, layer) {
return feature;
});
if (feature) {
alert("video comes here");
}
});
}
initMap();
invokeAddMarker();
</script>
</body>
</html>
I am facing two problem in the above code
1:the click event will fired 3 times ie, the number marker on the map that should only onces by theory
2:when i resize the div say(new width and height of the div is varied to new value in which the map is displayed)the markers will adjust to div but the event is not fired
please say why is this behavior and how to overcome it

Geocoding Address input Google Maps API

<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map-canvas { width: 1000px; height: 600px } /* ID */
</style>
<!--Include the Maps API JavaScript using a script tag.-->
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=false">
</script>
<script type="text/javascript">
//Function called when the window loads shown below in the addDomlistener
function initialize() {
var geocoder = new google.maps.Geocoder();
var mapOptions = { center: new google.maps.LatLng(40.5, -75.5), zoom: 8 };
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
}
function calcAddress(address)
{
var address = document.getElementById("address").value;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
//Got result, center the map and put it out there
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="panel">
<input id="address" type="text">
<input type="button" value="Search" onclick="calcAddress()" />
</div>
<div id="map-canvas"/>
</body>
</html>
I'm learning about google maps API, and I am just trying to get a simple address search to work, what am I missing? I've seen similar posts, but can't find what isn't right, might need some fresh eyes.
Varaibles map and geocoder are not visible outside of initialize() function. If you open console there is error written:
ReferenceError: geocoder is not defined
They should be made global like:
var map,
geocoder;
function initialize() {
geocoder = new google.maps.Geocoder();
var mapOptions = { center: new google.maps.LatLng(40.5, -75.5), zoom: 8 };
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
}
Additionaly, div tag is not self-closing.
<div id="map-canvas"/>
should be changed to
<div id="map-canvas"></div>