I'm trying to display markers on a map, but I am running in to difficulty, I'm not too skilled in the use of callbacks, can someone help me out thanks? I want multiple markers to show where different games are.
I'm using a rest api to retrieve the game details from the db, and I know this works, it's just after I retrieve them I can no longer access the data that has just been retrieved.
I am using ionic (Angular) and I am sure there is probably a better way of doing this. What is the best way to use a loop? If anyone could point out how I could improve my code. Here is what my controller for the map looks like
.controller('MapController', function($scope, $ionicLoading, gameFactory) {
$scope.initialise = function() {
...//set up map
});
$scope.map = map;
};
$scope.showGameMarkers = function() {
var map = document.getElementById("map");
gameFactory.getGames().success(function(data) {
//at this stage the data variable contains the details of my game
angular.forEach(data, function(key, data) {
//now data is empty
var latLng = new google.maps.LatLng(data.locationLatitude, data.locationLongitude);
console.log("latlang = "+latLng);
// Creating a marker and putting it on the map
var marker = new google.maps.Marker({
position: latLng,
title: data.locationName,
setMap : map
});
});
}).error(function(data) {
console.log("no games");
});
};
google.maps.event.addDomListener(document.getElementById("map"), 'load', $scope.initialise());
google.maps.event.addDomListener(document.getElementById("map"), 'load', $scope.showGameMarkers());
});
Thank you in advance!
It looks like you might have your key and data parameters reversed in your forEach loop. According to https://docs.angularjs.org/api/ng/function/angular.forEach it should be
angular.forEach(values, function(value, key) {
...
}
Related
I am having trouble trying to display the event name from an array of objects in a parsed JSON file within Google Maps Ionic framework. Right now I have the markers displaying for each event with a simple string called "testing" which displays fine. The problem is I am unsure of how to display each events name within this info window and not the string I made. Any help would be appreciated. I'll post the sample image I have now as well as the info window functionality below. Thanks!
what I have displaying now:
here
marker/info window functionality:
getMarkers(){
//this.http.get('assets/data/markers.json').map((res)=>res.json()).subscribe(data=>{
this.http.get('http://app.toronto.ca/cc_sr_v1_app/data/edc_eventcal_APR?limit=500').map((res)=>res.json()).subscribe(data=>{
this.addMarkersMap(data);
});
}
addMarkersMap(markers){
for(let marker of markers)
{
var loc = marker.calEvent.locations[0]['coords'];
console.log(loc);
marker = new google.maps.Marker({
position: loc,
map: this.map,
});
var infoWindow = new google.maps.InfoWindow({
content: markers.eventName
});
google.maps.event.addListener(marker, 'click', function(str)
{
return function() {
infoWindow.setContent(str);
infoWindow.open(this.map, marker);
}
}(markers.eventName));
}
}
I correct myself. You could benefit from a closure here.
Use a self-calling function to seal your parameter to the infowindow:
google.maps.event.addListener(marker, 'click', function(str)
{
return function() {
infoWindow.setContent(str);
infoWindow.open(this.map, marker);
}
}(markers.calEvent.eventName));
I'm trying to use angular-leaflet-directive with Websocket, though I'm able to integrate successfully, the positions of the markers are not getting updated dynamically. However The positions of map gets updated if I move mouse over the map but doesn't get updated when the lat-lng value changes.
Below is code snippet of module.
$scope.markers = {};
angular.extend($scope, {
bounds : $scope.bounds,
center : {},
kppaths : {},
events: {
markers:{
enable: [ 'move' ]
}
}
});
$stomp.setDebug(function(args) {
$log.info(args);
});
$scope.startWS = function() {
var connectionHeaders = {};
// Connect
$stomp.connect("/kp-ws").then(function(frame){
$log.info("connected to server")
$stomp.send('/app/start', {});
// Subscribe for message
$scope.subscription = $stomp.subscribe('/topic/kp', function(
data, headers, res) {
angular.forEach(data, function(k,v){
$scope.markers[k.markerId].lat = k.lat;
$scope.markers[k.markerId].lng = k.lng;
});
});
});
};
$scope.stopWS = function() {
$stomp.send('/app/stop', {});
$scope.subscription.unsubscribe();
$stomp.disconnect();
};
$scope.$on("leafletDirectiveMarker.move", function(event, args){
$log.info(args.model.lat);
});
} ]);
The html file
<div class="card-block">
<leaflet bounds="bounds" geojson="geojson" lf-center="center"
paths="kppaths" markers="markers" event-broadcast="events" width="100%" height="480px"></leaflet>
</div>
Is I'm missing something, Please let me know or suggest how to fix this issue?
The possible workaround I found is:
leafletData.getMap().then(function (map) {
$timeout(function() {map.invalidateSize()});
});
basically, once the map is invalidated, it updates markers' position. Although not perfect, considering some performance issues, the workaround at least solves the main issue.
I create a forEach loop. I can access data from Firebase with this loop and I can change variable. But I can not save these changes on Firebase. How can I save these changes? Here's my code:
var posts = $firebaseArray(ref);
posts.$loaded().then(function(item){
item.forEach(function(childSnapshot){
var num = childSnapshot.point-1;
childSnapshot.lastPoint = num;
});
});
You're using the AngularFire framework, which builds UI bindings on top of Firebase's regular JavaScript SDK. You should only be using it for things that you're binding to the Angular UI elements. For everything else, you're likely better off using Firebase's regular JavaScript SDK.
If I understand your requirement correctly, you're trying to loop over all child nodes in a database location once and modify a property. If so:
ref.once('value', function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var child = childSnapshot.val();
childSnapshot.ref().update({ lastPoint: child.point - 1 });
});
});
The relevant sections of the Firebase documentation are on reading data once and updating data.
Since AngularFire is built on top of Firebase's JavaScript SDK, they work perfectly together. So if elsewhere you bind the posts to the scope ($scope.posts = $firebaseArray(ref)), they will be updated automatically when you update the last point with the above snippet.
You can create a service that contains a getter and a setter. It would look something like this;
angular.module('app').factory("DataHandler",
function() {
var data;
return {
get: function() {
return data;
},
set: function(something) {
data = something;
}
}
}
);
Then in your code you would call:
var posts = $firebaseArray(ref);
posts.$loaded().then(function(item){
item.forEach(function(childSnapshot){
var num = childSnapshot.point-1;
childSnapshot.lastPoint = num;
DataHandler.set(childSnapshot);
});
});
Then wherever/whenever you need to get that data just call:
Datahandler.get();
I'm trying to show different maps in different views but charging 1 on 1 map view, switch to another map not load, there is no mistake to launch the browser so I could not decide because I can not keep showing other maps. I'm doing as follows:
$scope.cargarUbicacion = function () {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
latitud_actual = position.coords.latitude;
longitud_actual = position.coords.longitude;
console.log(latitud_actual);
console.log(longitud_actual);
var mapOptions = {
center: new google.maps.LatLng(latitud_actual, longitud_actual),
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scrollwheel: false
};
map = new google.maps.Map(document.getElementById("mapa_ubicacion"), mapOptions);
$scope.setMarker(map, new google.maps.LatLng(latitud_actual, longitud_actual), 'Yo', '');
});
}
}
$scope.setMarker = function(map, position, title, content) {
var marker;
var markerOptions = {
position: position,
map: map,
title: title,
icon: 'http://maps.google.com/mapfiles/ms/icons/green-dot.png'
};
marker = new google.maps.Marker(markerOptions);
markers.push(marker); // add marker to array
google.maps.event.addListener(marker, 'click', function () {
// close window if not undefined
if (infoWindow !== void 0) {
infoWindow.close();
}
// create new window
var infoWindowOptions = {
content: content
};
infoWindow = new google.maps.InfoWindow(infoWindowOptions);
infoWindow.open(map, marker);
});
}
I am using this code in multiple controllers, my idea is encapsulated and can occupy the same code 1 time in several views. Whenever I change the id map to avoid that problem, thinking that this was the cause that did not load the map.
Any idea how to do what I need or that is failing to load maps?
Thank you.
I personnaly do the following :
The code taht you want to reuse put it into a global variable such as :
Then into your control, you can extend it with this mapExtend
global.MapExtend = function($scope, $rootScope, leafletData) {
// ... all your functions to reuse
};
// In your main controler, extend it with your map capabilities with angular.extend
angular.extend(myCtrl, new MapExtend($scope, $rootScope, leafletData));
I have a map and search-box instantiated and dropping a marker after search is completed. This is working properly, however, I want to query the places services to get places nearby where my marker is dropped and I am getting an error that when running: google.maps.places.PlacesService(map) Uncaught TypeError: undefined is not a function...
Below is some relevant code
In my Angular.module.config:
uiGmapGoogleMapApiProvider.configure({
v: '3.17',
libraries: 'places'
});
In my maps controller:
1) callback when loaded
uiGmapGoogleMapApi.then(function(maps) {
$scope.googleMapsObject = maps;
});
2) setup the event handler to create the marker
$scope.searchbox = {
events: {
places_changed: placesChangedHandler
}
}
3) handle when places are changed, set the marker for lat, and (LAST LINE IS THE PROBLEM) query for the name of the place.
function placesChangedHandler(searchBox) {
var lat = searchBox.getPlaces()[0].geometry.location.k;
var lgn = searchBox.getPlaces()[0].geometry.location.C;
var center = { latitude: lat , longitude: lgn };
$scope.address = searchBox.getPlaces()[0].adr_address;
$scope.map = {
center: center, zoom: 15
};
setMarker(center);
var service = new google.maps.places.PlacesService($scope.googleMapsObject);
// service.nearbySearch(request, callback);
}
The error is on that second to last line. (also, is there a cleaner way to get to those variables?)
Thanks in advance for your help!
I faced the same problem recently and it took time to understand what is wrong because I'm new to angular (to be honest I'm new to Java Script;) )
In your controller you need add $window dependency to access global object google. Here is how it can look like:
.controller('mapCtrl', ['$scope', '$window', 'uiGmapGoogleMapApi'
, function($scope, $window, GoogleMapApi) {
GoogleMapApi.then(function(map) {
$scope.googleVersion = map.version;
$scope.map = { center: { latitude: 59.9500, longitude: 10.7500 }, zoom: 11 };
$scope.googleMapsObject = map
var service = new $window.google.maps.places.PlacesService($scope.googleMapsObject);
});
}])
I think the issue is you are trying to load the places service on the "maps" returned value which is the google.maps object.
so:
$scope.googleMapsObject == google.maps
what you need is to either use the markers directive (which I havent tried yet) or go on the actual map object for your map which you can get from the tilesLoaded event.
$scope.map = {
events: {
tilesloaded: function (map) {
$scope.$apply(function () {
$scope.actualMapObj = map;
$log.info('this is the map instance', map);
});
}
}
}
tilesLoaded from faq: http://angular-ui.github.io/angular-google-maps/#!/faq
After you initialize it with 'places' as library you should have the places property in the api parameter
uiGmapGoogleMapApi.then(function(maps) {
maps.places.PlacesService() // -> here you can search for something
});