I'm making a little app for AngularJS personal training, and i'm getting a few errors.
I receive Json data from an API, and then I want to display amarker for every object I get. The problem is that I have a console error, so I supposed I've made a mistake.
Here goes my controller
toulouseVeloControllers.controller('toulouseVeloListCtrl', ['$scope', '$http',
function($scope, $http) {
angular.extend($scope, {
osloCenter: {},
markers: {},
defaults: {
scrollWheelZoom: false
}
});
$http.get('https://api.jcdecaux.com/vls/v1/stations?contract=toulouse&apiKey=*********************************').success(function(data) {
$scope.bornes = data;
for (var i = 0; i < data.length; i++) {
$scope.markers.osloMarker = {
lat: data[i].position.lat,
lng: data[i].position.lng,
message: data[i].name,
focus: true,
draggable: false
};
$scope.osloCenter = {
lat: data[1].position.lat,
lng: data[1].position.lng,
zoom: 15
};
}
console.log(data.position.lat);
console.log(data.position.lng);
});
}]);
In my map I only have a marker for my last object. And in the console I have "TypeError: Cannot read property 'lat' of undefined"
When I try to display all my object outside of the map, in a list with ng-repeat, I have no problem.
Here go my HTML :
<div ng-controller="toulouseVeloListCtrl">
<leaflet markers="markers" center="osloCenter" style="width: 100%; height: 500px;"></leaflet>
</div>
Any idea of what is wrong ?
Thank you a lot !!
I guess that problem is:
console.log(data.position.lat);
Maybe you should use :
console.log(data[i].position.lat);
And also:
$scope.markers=[];
$scope.osloCenter=[];
for (var i = 0; i < data.length; i++) {
$scope.markers[i].osloMarker = {
lat: data[i].position.lat,
lng: data[i].position.lng,
message: data[i].name,
focus: true,
draggable: false
};
$scope.osloCenter[i] = {
lat: data[1].position.lat,
lng: data[1].position.lng,
zoom: 15
};
}
Related
I have a two components. first one is for the articles content that I am looping. And second one is google map for the articles addresses... They are connected in store.js. No problem with that. And I am trying to center the map to if any articles's id clicked in component one. But having some problems about how to implement clicked event to google map component's listener?
What I thought, using event bus for the situation. And send which "id" clicked.
UPDATED
articles component
<table>
<tbody>
<tr :key="item.id" v-for="item in articles" #clicked="changeCenter(item.id)">
<th>
<img :src="item.image" alt="">
</th>
<td>
<p>{{item.name}}</p>
<p>{{item.address.substr(0,40)}}...</p>
</td>
<td>
<router-link :to="{ name: 'detail', params: {id:item.id} }"><i class="fas fa-chevron-right"></i></router-link>
</td>
</tr>
</tbody>
</table>
And add the method.
methods: {
changeCenter(id){
eventBus.$emit("centerMap", id);
},
},
and on the other side google map component is below.
in created() hook I am catching the id that clicked. But I can't access the value inside the buildMarkers() function. I mean I can console.log(this.centerid) in created() hook there is no problem. I can see the data that I am passing. But when the time come to put the this.centerid in the buildMarkers() or any other methods, centerid is start to being undefined
created(){
eventBus.$on("centerMap", (id) => {
this.centerid = id;
})
},
and rest is a a bit mistery to me. google map code is right below.
data(){
return {
markers:[],
infoWindows: [],
centerid: "",
};
},
mounted(){
this.initMap();
this.clearMarkers();
this.buildMarkers();
},
created(){
eventBus.$on("centerMap", (id) => {
this.centerid = id;
})
},
watch: {
articles(){
this.clearMarkers();
this.buildMarkers();
}
},
methods: {
initMap(){
const japan = {
lat: 35.652832,
lng: 139.839478
}
this.map = new google.maps.Map(document.getElementById("map"), {
zoom: 7,
// maxZoom: 10,
center: {lat: japan.lat, lng: japan.lng}
})
},
buildMarkers(){
var map = this.map;
this.markers = [];
for(var i = 0; i < this.articles.length; i++){
// some codes...
// some codes...
var marker = new MarkerWithLabel({
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 0
},
position: position,
map: this.map,
labelClass: "markerClass",
labelAnchor: new google.maps.Point(30, 30),
labelContent: label,
});
this.markers.push(marker);
if (this.articles[i].id === this.centerid) {
google.maps.event.addListener(marker, function () {
infowindow.open(map, this);
map.setCenter(this.getPosition());
map.setZoom(10);
});
}
}
},
clearMarkers(){
for( var i = 0; i < this.markers.length; i++ ){
this.markers[i].setMap( null );
}
},
},
The problem is at this part. I am not sure how to handle this. Like I said before. I can't access the centeridto 's value.
if (this.articles[i].id === this.centerid) {
google.maps.event.addListener(marker, function () {
infowindow.open(map, this);
map.setCenter(this.getPosition());
map.setZoom(10);
});
}
So in my Rails app I am building out a region show page with multiple locations. Users are able to insert new locations and map markers need to be dynamically placed based on the latitude and longitude that they enter. In my Region show page I have the following:
<div class="container-fluid">
<div class="row">
<div class="banner" id="region-banner" data-region-name="<%=#region.name.downcase%>">
<script>document.addEventListener('DOMContentLoaded',app.regions);</script>
Then in my region.js file I have the following:
import { tns } from 'tiny-slider/src/tiny-slider.module';
import { mapStyle } from './styles/mapStyle';
app.regions = () => {
function init() {
startGoogleMap();
}
let startGoogleMap = () => {
let map = new google.maps.Map(document.getElementById('region-banner'), {
zoom: 3,
minZoom: 3,
disableDefaultUI: true,
gestureHandling: 'cooperative',
styles: mapStyle
});
var mapElement = document.getElementById('region-banner');
const regionName = mapElement.getAttribute('data-region-name');
let bounds = new google.maps.LatLngBounds();
let promise = $.getJSON('/locations.json');
promise.done(function(data) {
return $.each(data, function() {
return new google.maps.Marker({
position: {
lat: parseFloat(data.lat),
lng: parseFloat(data.lng) },
map: map,
icon: "/marker.png"
});
});
});
console.log(promise);
map.fitBounds(bounds);
};
return init();
};
Then in my controller I have:
def show
#locations = Location.all
respond_to do |format|
format.json { render json: #locations }
format.html
end
end
So no real errors are applying however...nothing appears. The console shows the responseText:“[{“id”: 5, “name”: “Chicago”, “abbreviation”: “CHI”, “lat”: “44.222”, “lng”: “-22.111”}, {“id”: 6, “name”: “Frankfort”, “abbreviation”: “FKT”, “lat”: “41.3232”, “lng”: “-19.5221”} ]”. Which really on this page I should only need/use the first.
Shouldn't it also be applying the markers at this stage since I put in the position?
this is the code responsible for setting your Markers.
I would focus on understanding why promise.done() does not run create the new google.maps.Marker() for each row in your (data) from your response.
Maybe the problem is connected to the /marker.png
promise.done(function(data) {
return $.each(data, function() {
return new google.maps.Marker({
position: {
lat: parseFloat(data.lat),
lng: parseFloat(data.lng) },
map: map,
icon: "/marker.png"
});
});
});
Whenever one of the regions on the map are clicked, it should open the window for that region, but it doesn't.
The expected results would be as follows:
Here is how I want it to look.
Here is my html:
<ui-gmap-polygon static="true" ng-repeat="p in regions track by p.id" path="p.path" visible="p.visible" stroke="p.stroke" fill="p.fill" events="events" clickable="true" >
</ui-gmap-polygon>
<ui-gmap-windows models="markers" show="show">
<!-- Window Code -->
</ui-gmap-windows>
Here is the $scope.events.click function for the polygons:
for(var i = 0; i < $scope.markers.length; i++) {
//console.log(model.path[0].id + " == " + $scope.markers[i].id);
if(model.path[0].id == $scope.markers[i].id) {
console.log("Showing window " + model.path[0].id);
$scope.markers[i].show = true;
}
else
{ // hides other windows
$scope.markers[i].show = false;
}
}
Something to note. The log statement does show up, just not the window.
Here is a plunker: Plunker
I guess you want to add multiple polygons so change your html to:
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="options" bounds="map.bounds">
<ui-gmap-polygons static="true" models="regions" path="'path'" visible="true" stroke="'stroke'" fill="'fill'" events="events" clickable="true" >
</ui-gmap-polygons>
<ui-gmap-windows models="markers" show="'show'" coords="'coords'">
<div ng-non-bindable>Test</div>
</ui-gmap-windows>
</ui-gmap-google-map>
You need to define the property which will define the value as string e.g.: show="'show'" coords="'coords'"
I added a second model just because i wanted to test it which multiple values. So my controller looks like this:
...
$scope.regions = [
{
id: 0,
path: [
{latitude: 39.13773735160255, longitude: -86.51972115039825, id: 0},
{latitude: 39.137606286024926, longitude: -86.51961386203766},
{latitude: 39.137664537422864, longitude: -86.51949316263199},
{latitude: 39.13779768329436, longitude: -86.51960045099258}
]
},
{
id: 1,
path: [
{latitude: 39.13673735160255, longitude: -86.51972115039825, id: 1},
{latitude: 39.136606286024926, longitude: -86.51961386203766},
{latitude: 39.136664537422864, longitude: -86.51949316263199},
{latitude: 39.13679768329436, longitude: -86.51960045099258}
]
}
]
$scope.markers= [{
id: 0,
show: true,
coords: { //you need an object containing latitude and longitude, so i wrapped these properties into coords
latitude: 39.13773735160255,
longitude: -86.51972115039825
}
},{
id: 1,
show: true,
coords: {
latitude: 39.13673735160255,
longitude: -86.51972115039825
}
}
]
$scope.events = {
click: function(polygon, eventName, model) {
// show the window
for(var i = 0; i < $scope.markers.length; i++) {
if(model.path[0] && model.path[0].id == $scope.markers[i].id) {
$scope.markers[i].show = true;
console.log("Window Displayed")
} else {
$scope.markers[i].show = false;
}
}
}
};
You should change your data models if you can e.g. regions where id is defined twice.
I figured out an alternative solution to the problem. Instead of using a window for every marker, I used just one:
<ui-gmap-window coords="selected" show="windowShown" closeClick="closeClick()">
<!-- Window Code -->
</ui-gmap-window>
Then in the controller we have a similar click function:
/*
Events when clicking on a polygon.
*/
$scope.events = {
click: function(polygon, eventName, model) {
// show the window
for(var i = 0; i < $scope.markers.length; i++) {
if(model.path[0].id == $scope.markers[i].id) {
$scope.selected = $scope.markers[i];
$scope.windowShow = true;
}
}
}
};
Lastly, we have a closeClick function to make sure $scope.windowShown is set to false after the window is closed. Otherwise, you cannot reopen the window on the same polygon after it has been closed.
$scope.closeClick = function() { $scope.windowShow = false; }
I use google maps api angular (https://angular-ui.github.io/angular-google-maps/#!/api/windows) to display a map with a mark on it. The marked point, has its label with a few paragraphs and a picture.
The content of paragraphs displayed correctly, but not the image. The url of it is correct. Can add an image?
Some code:
HTML
<ui-gmap-google-map center='datos.mapa.center' options="datos.mapa.opciones" zoom='datos.mapa.zoom'>
<ui-gmap-marker coords="datos.marker_club.coords"
options="datos.marker_club.options"
idkey="datos.marker_club.id"
click="markerClick" >
<ui-gmap-window show="datos.marker_club.show"
closeClick="markerClose(marker)" >
<div><img class="mapa_escudo" scr="{{datos.escudo}}" width="32" height="32" />{{datos.club}}<br />Sede {{datos.sede}}</div>
</ui-gmap-windows>
</ui-gmap-marker>
</ui-gmap-google-map>
JS
$scope.datos.club = 'Club';
$scope.datos.sede = 'Sede';
$scope.datos.escudo = 'http://www.server.com/image.png';
uiGmapGoogleMapApi.then(function(maps) {
$scope.datos.mapa = { center: { latitude: latitud, longitude: longitud }, zoom: zoom };
$scope.datos.mapa.opciones = { scrollwheel: true };
var icon = "http://maps.google.com/mapfiles/ms/icons/orange-dot.png";
$scope.datos.marker_club = { id: 1,
coords: { latitude: latitud, longitude: longitud},
options:{
draggable: false,
icon: new google.maps.MarkerImage(icon),
},
}; $scope.markerClick = function(marker, eventName, model) {
$scope.datos.marker_club.show = !$scope.datos.marker_club.show;
};
$scope.markerClose = function(marker) {
$scope.datos.marker.show = false;
};
Sorry, just missing "ng-src" in the definition of the image!
I'm using angular google maps with ionic framework and trying to get coordinates on click. In view directive is injected like so
<ui-gmap-google-map center="map.center" zoom="map.zoom" dragging="true" options="map.options" events="map.events"></ui-gmap-google-map>
And here is my controller part
angular.extend($scope,
$scope.map = {
center: {latitude: 53.902407, longitude: 27.561621 },
zoom: 15,
options: {
maxZoom: 16,
minZoom: 13,
styles: mapStyles.bright
},
events: {
click: function (mapModel, eventName, originalEventArgs) {
$log.info("user defined event: " + eventName, mapModel, originalEventArgs);
var e = originalEventArgs[0];
var lat = e.latLng.lat(),
lon = e.latLng.lng();
console.log('You clicked here ' + 'lat: ' + lat + ' lon: ' + lon);
//scope apply required because this event handler is outside of the angular domain
$scope.$apply();
}
}
});
Event part is basically copy-pasted from examples in docs. However, when I click it, I get an error
Where did I go wrong?
UPD Somehow $scope.map.events is undefined, although I can, for instance, console.log it and see that it's defined before the error occurs. Same error is happening for all events. For example,
events: {
tilesloaded: function (map) {
$scope.$apply(function () {
$scope.mapInstance = map;
$log.info('tiles loaded');
});
}
}
returns
Uncaught TypeError: Cannot read property 'tilesloaded' of undefined
in console with the same stacktrace.
You have mixed two ways of bringing something into scope; assignment to scope and extending scope. Either extend the $scope with an object (ie not $scope.map =)
and your code becomes...
angular.extend($scope,{
map: {
center: {latitude: 53.902407, longitude: 27.561621 },
zoom: 15,
options: {
maxZoom: 16,
minZoom: 13,
styles: mapStyles.bright
},....
})
or use assignment to scope
$scope.map = {
center: {latitude: 53.902407, longitude: 27.561621 },
zoom: 15,
options: {
maxZoom: 16,
minZoom: 13,
styles: mapStyles.bright
},....
http://moduscreate.com/angularjs-tricks-with-angular-extend/