I have created an angularJS directive to call the google maps api. The directive looks like that:
angular.module('sbAdminApp')
.directive('allWash', function () {
return {
templateUrl: 'static/app/scripts/directives/googleMap/allWash.html',
restrict: 'E',
replace: true,
controller: function ($scope, WashService) {
$scope.initMap = new function () {
var locations = [
['Bondi Beach', 52.229676, 21.012228999999934, 4],
['Coogee Beach', 52.14276459999999, 21.02135450000003, 5],
['Cronulla Beach', -34.028249, 151.157507, 3],
['Manly Beach', -33.80010128657071, 151.28747820854187, 2],
['Maroubra Beach', -33.950198, 151.259302, 1]
];
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: new google.maps.LatLng(-33.92, 151.25),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infowindow = new google.maps.InfoWindow();
var marker, i;
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][1], locations[i][2]),
map: map
});
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
infowindow.setContent(locations[i][0]);
infowindow.open(map, marker);
}
})(marker, i));
}
}
}
}
});
The google also demands to create a key which I actually created and put it into the index.html file, like that:
<script src="http://maps.google.com/maps/api/js?key=AIzaSyD5bgIqM-C7WVWkaGDa0AE2luY-dbF6nBA"
async defer
type="text/javascript"></script>
My html file (allWash.html file which is connected to the directive) looks like:
<script type="text/ng-template" id="allWash.html">
<div>
<div id="map" style="width: 600px; height: 600px;" ng-init="initMap()"></div>
</div>
</script>
When I want to call the diretive at diffrent html page I do <all-wash></all-wash>
The whole code creates a fail:
I think it is connected to the google key which I put into index.html file, but I'm not sure so that I don't know how to solve this issue.
You may refer with this thread. This error might happen if you load the script before the DOM was loaded. Try to move the script to the end of body and check if it works.
Also, it might be due to the map div not being rendered before the javascript runs that needs to access it. Check it here. "You should put your initialization code inside an onload function or at the bottom of your HTML file, just before the tag, so the DOM is completely rendered before it executes (note that the second option is more sensitive to invalid HTML)."
Related
I am trying to show a google map on my AngularJs app. I used below code and when run, map not displayed. Just a blank page. No errors on browser console.
Here is the Fiddle
HTML Code
<div class="row">
<div id="google-maps"></div>
</div>
Controller Code
function initialize() {
var mapCanvas = document.getElementById('google-maps');
var mapOptions = {
center: new google.maps.LatLng(44.5403, -78.5463),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(mapCanvas, mapOptions);
}
$timeout(function(){
initialize();
}, 100);
Also I have this code in index.html file
<script src="https://maps.googleapis.com/maps/api/js?key=my_key&libraries=places"></script>
Try calling initialize() inside document.ready:
$(initialize);
Also give a width and height to your container div.
Working Fiddle
I am making this app with the help of google maps, i am successfully adding waypoints in a route and making a route between them. But on dbclick i remove that way point from the map. Now when i make the route it includes the deleted waypoint too. Because of the fact it does not delete from the waypoint array.
The question is how can i remove a specific waypoint from the waypoint array. I dont have any index of something.
pushing waypoints
/* Whenever a user taps a pin it goes into pinwapypts */
pinwaypts.push({
location: $scope.destination_route,
stopover: true,
});
Add waypoints in map
infowindow.open($scope.map, marker);
$scope.markers.push(marker);
google.maps.event.addListener(marker, 'click', function () {
infowindow.setContent($scope.results[0].formatted_address);
infowindow.open($scope.map, this);
});
removing waypoint marker from map
google.maps.event.addListener(marker, 'dblclick', function () {
$scope.markers.pop().setMap(null);
});
Now how can i remove a specific waypoint from its array ?
full code
function getClickLoc(latlng) {
var geocoder = new google.maps.Geocoder;
geocoder.geocode({
'location': latlng
}, function (results, status) {
$scope.results = results;
//console.log(results);
if (status === 'OK') {
if (results[0]) {
$scope.map.setZoom(12);
var marker = new google.maps.Marker({
position: latlng,
map: $scope.map
});
infowindow.setContent(results[0].formatted_address);
$scope.destination_route = latlng;
/* Whenever a user taps a pin it goes into pinwapypts */
pinwaypts.push({
location: latlng,
stopover: true
});
$scope.$apply();
infowindow.open($scope.map, marker);
$scope.markers.push(marker);
google.maps.event.addListener(marker, 'dblclick', function () {
infowindow.setContent($scope.results[0].formatted_address);
infowindow.open($scope.map, this);
});
google.maps.event.addListener(marker, 'dblclick', function () {
$scope.markers.pop().setMap(null);
});
//$ionicLoading.hide();
} else {
window.alert('No results found');
}
} else {
window.alert('Something went wrong, Please try again.');
//window.alert('Geocoder failed due to: ' + status);
}
});
}
Your full code has a lot of missing things, so I gave a best-effort to create a minimal, complete, and verifiable example out of it. This assumes you create a waypoint each time you create a marker. And markers are created via click/tap on the map.
When removing a waypoint from an array, you can get its index using indexOf. So inside your listener for dblclick, you get the index by doing:
var wayptIndex = $scope.pinwaypts.indexOf(waypoint);
and then splicing it by:
$scope.pinwaypts.splice(wayptIndex, 1);
I provided the example code below (Be sure to use your own API KEY) and you'll notice the listener is in a closure. This is so that I can still pass the waypoint variable to it, without it losing scope.
You can also check this jsbin link
P.S.
Your removal of markers is also incorrect. Do not do a pop() as that only removes the last item in the array. If you double click a middle array, it will still remove the last item. I also used indexOf to get the marker's correct index.
Hope this helps and hope you can create minimal and complete examples next time! :)
(function(angular) {
'use strict';
angular
.module('ngApp', [])
.controller('demoController', demoController);
function demoController($scope) {
initMap();
$scope.pinwaypts = [];
$scope.markers = [];
function initMap() {
$scope.map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: -34.397,
lng: 150.644
},
zoom: 8
});
$scope.map.addListener('click', getClickLoc);
}
function getClickLoc(e) {
var latlng = e.latLng;
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
'location': latlng
}, function(results, status) {
$scope.results = results;
if (status === 'OK') {
if (results[0]) {
var marker = new google.maps.Marker({
position: latlng,
map: $scope.map
});
$scope.map.panTo(latlng);
$scope.map.setZoom(12);
// you did not show how you instantiated your infowindow so I added this
var infowindow = new google.maps.InfoWindow();
infowindow.setContent(results[0].formatted_address);
$scope.markers.push(marker);
$scope.destination_route = latlng;
/* Whenever a user taps a pin it goes into pinwapypts */
var waypoint = {
location: latlng,
stopover: true
};
$scope.pinwaypts.push(waypoint);
// I'm not sure if you still really need this.
$scope.$apply();
infowindow.open($scope.map, marker);
google.maps.event.addListener(marker, 'click', function() {
// This is redundant. You can just open the infowindow on click of the marker // infowindow.setContent($scope.results[0].formatted_address);
infowindow.open($scope.map, this);
});
(function(waypoint, marker) {
google.maps.event.addListener(marker, 'dblclick', function() {
// Pop has an issue. You will only remove the last marker from your array,
// not the specific marker the user is double-clicking.
// $scope.markers.pop().setMap(null);
var markerIndex = $scope.markers.indexOf(marker);
// You don't remove the markers from the array. Just set them to setMap(null)
// removing them will mess up their indeces and this will no long work
// just refresh the markers array on a new request or something
$scope.markers[markerIndex].setMap(null);
// Get the index of the waypoint and this once you remove so that
// it's not included when you do a directions service request
var wayptIndex = $scope.pinwaypts.indexOf(waypoint);
$scope.pinwaypts.splice(wayptIndex, 1);
});
}(waypoint, marker))
} else {
window.alert('No results found');
}
} else {
window.alert('Something went wrong, Please try again.');
}
});
}
}
})(window.angular);
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body,
#view {
height: 100%;
margin: 0;
padding: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<!-- BE SURE TO USE YOUR OWN API KEY. This loads the script synchronously and I call initMap manually inside my controller. For demo purposes only. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAZVylT7o5OxdosVfh-IVONHoaA0cpN5VI"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.js"></script>
</head>
<body ng-app="ngApp">
<div id="view" ng-controller="demoController">
<div id="map"></div>
</div>
</body>
</html>
After adding Leaflet to my AngularJS app:
<leaflet id="map" defaults="defaults" center="center" bounds="bounds" controls="controls" event-broadcast="events"></leaflet>
And setting it up:
// Initialise the feature group to store editable layers
var drawnItems = new L.FeatureGroup();
// Initialise the draw control
var drawControl = new L.Control.Draw({
position: 'topright',
edit: {
featureGroup: drawnItems
}
});
// Configure Leaflet
angular.extend($scope, {
defaults: {
zoomControlPosition: 'topright',
minZoom: 3,
tileLayerOptions: {
detectRetina: true,
reuseTiles: true,
attribution: 'OpenStreetMaps'
}
},
center: {},
controls: {
custom: [drawControl]
},
events: {
map: {
enable: ['click']
}
}
});
Following this code it doesn't get evaluated (no error shown though):
leafletData.getMap().then(
function (map) {
alert('I have accessed the map.');
}
);
This should show me an alert straight away, although nothing happens.
If I delay this previous code, for example, running it in a function on a button click, it works!
Does anyone knows what could be a problem?
Seeing example, it should work: https://github.com/tombatossals/angular-leaflet-directive/blob/master/examples/control-draw-example.html
PARTLY SOLVED
Removing ID from leaflet HTML tag solved the problem. Must be a bug.
You are supposed to pass the id specified in the <leaflet> tag to getMap() function.
In your example, the id is map. You would pass it like this:
leafletData.getMap("map").then(
function (map) {
alert('I have accessed the map.');
}
);
I want to use angular-ui for google maps. From the example, it passes a hard-coded coordinate.
$scope.mapOptions = {
center: new google.maps.LatLng(35.784, -78.670),
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
Then use it on the directive.
<div id="map_canvas" ui-map="myMap" class="map" ... ui-options="mapOptions">
</div>
But I need the coordinates to be the user location, to get that, I need to use navigator.geolocation.getCurrentPosition() which I got the coordinate in a callback.
I'm thinking of something like:
navigator.geolocation.getCurrentPosition(function(result) {
angular.bootstrap(myElement, ['myModule']); // I need a way to inject "result" to the module
}, function(error) {
// fallback to default coordinate.
});
Any suggestion?
Add the constant to the module before bootstrapping:
angular.module('myModule', [])
.controller('MyController', function($scope, coordinates){
$scope.coordinates = coordinates;
})
navigator.geolocation.getCurrentPosition(function(result) {
angular.module('myModule').constant('coordinates', result);
angular.bootstrap(document, ['myModule']);
}, function(error) {
// fallback to default coordinate.
});
Demo
I'm having trouble rendering Google Maps (V3) with Backbone.js.
It fails to load when I navigate to map view (/#/map); however, the map somehow loads perfectly fine when I hit refresh in that map view url.
Relevant Code Below:
<body>
Home
<div id="content"></div>
<script type="text/template" id="home_template">
Go !
</script>
<script type="text/template" id="map_template">
<div id="map"></div>
</script>
</body>
var MapView = Backbone.View.extend({
el: '#content',
render: function() {
var template = _.template($('#map_template').html());
var init = function() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map"),
mapOptions);
}
google.maps.event.addDomListener(window, 'load', init);
this.$el.html(template);
}
});
var Router = Backbone.Router.extend({
routes: {
"" : "home",
"map" : "map"
}
});
var router = new Router;
var homeView = new HomeView();
router.on('route:home', function() {
homeView.render();
});
var mapView = new MapView();
router.on('route:map', function() {
mapView.render();
});
Backbone.history.start();
It seems that 'something' is missing when I'm switching views between home and map, but I'm not sure what that 'something' is. I believe I have combed through relevant questions, but cannot find the missing point.
Any help would be much appreciated.
Thank you!
(P.S The Mapview part is taken from : https://developers.google.com/maps/documentation/javascript/tutorial
)
Problem is here I guess
google.maps.event.addDomListener(window, 'load', init);
you are calling init on window.load, but when you switch between view, it will not refresh the page, and window.load never get triggered. I guess you need to change the way init happening, I could be able to suggest better if I have more information about DOM structure of the page.