Pass an object as part of ng-map marker - angularjs

Using markers in ng-map with angular JS
<ng-map zoom-to-include-markers="auto" default-style="false" class="myMap">
<marker ng-repeat="Customer in ListForDisplay" position="{{Customer.location.lat}},{{Customer.location.lng}}" icon="{{Customer.icon}}" clickedaddress="{{Customer.address}}" clickedextras="{{Customer.extrasString}}" data="{{Customer}}" on-click="markerSingleClick($event)" on-dblclick="markerDoubleClick($event)"></marker>
</ng-map>
I can access the string variables in the controller, but the object data still stays undefined in debugging sessions:
$scope.markerSingleClick = function (event) {
var clickedaddress = this.clickedaddress;
var clickedextras = this.clickedextras;
var data = this.data;
Is there a way to pass an entire object as part of the marker, rather than single string properties

To pass current object as a parameter via marker on-click event, replace
on-click="markerSingleClick($event)"
with
on-click="markerSingleClick({{Customer}})"
and then update markerSingleClick function:
$scope.markerSingleClick= function (event,customer) {
//...
};
Working example
angular.module('mapApp', ['ngMap'])
.controller('mapCtrl', function ($scope, NgMap) {
NgMap.getMap().then(function (map) {
$scope.map = map;
});
$scope.cities = [
{ id: 1, name: 'Oslo', pos: [59.923043, 10.752839] },
{ id: 2, name: 'Stockholm', pos: [59.339025, 18.065818] },
{ id: 3, name: 'Copenhagen', pos: [55.675507, 12.574227] },
{ id: 4, name: 'Berlin', pos: [52.521248, 13.399038] },
{ id: 5, name: 'Paris', pos: [48.856127, 2.346525] }
];
$scope.showInfo = function (event,city) {
alert(JSON.stringify(city));
//console.log(city);
};
});
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key="></script>
<script src="https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/scripts/ng-map.js"></script>
<div ng-app="mapApp" ng-controller="mapCtrl">
<ng-map zoom="5" center="59.339025, 18.065818">
<marker ng-repeat="c in cities" position="{{c.pos}}" title="{{c.name}}" id="{{c.id}}" on-click="showInfo({{c}})">
</marker>
</ng-map>
</div>
Another option would be to pass object identifier as a parameter, for example its index:
<marker ng-repeat="c in cities" on-click="showInfo($index)" position="{{c.pos}}" title="{{c.name}}" id="{{c.id}}">
</marker>
Then current object could be determined like this:
$scope.showInfo = function (event,index) {
var currentCity = $scope.cities[index];
//console.log(currentCity);
};

Related

Check if the marker is inside the circle radius AngularJS

I'm trying to know if a given marker is inside a circle radius. And I want to know if the marker is clicked so it will show an alert about the marker's position. I'm using ng-map.
Sample map image
My HTML :
<html ng-app="myApp">
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAHmXV5zem_Py_aFHAwPixEyjW1cV-gJ00&callback=initMap"type="text/javascript"></script>
<script src="https://code.angularjs.org/1.3.15/angular.js"></script>
<script src="https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/scripts/ng-map.js"></script>
</head>
<body ng-controller="MyController as vm">
<br/>
<br/>
<br/>
<ng-map zoom="11" center="{{vm.latlng}}" on-click="vm.setCenter(event)" tilt="0">
<marker position="[-6.5829106488490865, 106.87462984179683]" on-click="vm.foo(2,3)" draggable="true"></marker>
<shape name="circle" stroke-color='#FF0000' stroke-weight="2"
center="{{vm.latlng}}" radius="{{vm.radius}}"
on-click="vm.getRadius()"
draggable="true"
on-dragstart="vm.dragStart()"
on-drag="vm.drag()"
on-dragend="vm.dragEnd()"
editable="true">
</shape>
<traffic-layer></traffic-layer>
</ng-map>
</body>
</html>
My Controller :
var app = angular.module('myApp', ['ngMap']);
app.controller('MyController', function(NgMap) {
var map;
var vm = this;
NgMap.getMap().then(function(evtMap) {
map = evtMap;
});
vm.latlng = [-6.584957, 106.804592];
vm.radius = 5000;
vm.getRadius = function(event) {
alert('this circle has radius ' + this.getRadius());
alert('Titik Tengah : ' + this.getCenter());
}
vm.setCenter = function(event) {
console.log('event', event);
map.setCenter(event.latLng);
}
vm.foo = function(event, arg1, arg2) {
alert('this is at '+ this.getPosition());
}
vm.dragStart = function(event) {
console.log("drag started");
}
vm.drag = function(event) {
console.log("dragging");
}
vm.dragEnd = function(event) {
console.log("drag ended");
}
});
Thank you
To determine whether a marker within a circle there is google.maps.geometry.spherical.computeDistanceBetween function from geometry library
Prerequisites
load geometry library, for example:
https://maps.google.com/maps/api/js?key=--YOUR KEY GOES HERE--&libraries=geometry
The example demonstrates how to determine whether a marker is within a area(circle) and renders it with different icon:
angular.module('mapApp', ['ngMap'])
.controller('mapController', function ($scope, NgMap) {
NgMap.getMap().then(function (map) {
$scope.map = map;
});
$scope.center = [59.339025, 18.065818];
$scope.radius = 500 * 1000; //in meters
$scope.locations = [
{ id: 1, name: 'Oslo', pos: [59.923043, 10.752839] },
{ id: 2, name: 'Stockholm', pos: [59.339025, 18.065818] },
{ id: 3, name: 'Copenhagen', pos: [55.675507, 12.574227] },
{ id: 4, name: 'Berlin', pos: [52.521248, 13.399038], },
{ id: 5, name: 'Paris', pos: [48.856127, 2.346525] }
];
let centerLatLng = new google.maps.LatLng($scope.center[0],$scope.center[1]);
$scope.locations.forEach((loc,i) => {
let pos = new google.maps.LatLng(loc.pos[0],loc.pos[1]);
if (google.maps.geometry.spherical.computeDistanceBetween(pos, centerLatLng) <= $scope.radius) {
loc.icon = {"url": "http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png"};
}
});
});
<script src="https://maps.google.com/maps/api/js?libraries=geometry"></script>
<script src="https://code.angularjs.org/1.3.15/angular.js"></script>
<script src="https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/scripts/ng-map.js"></script>
<div ng-app="mapApp" ng-controller="mapController">
<ng-map default-style="true" zoom="4" center="{{center}}">
<marker ng-repeat="l in locations" icon='{{l.icon}}' position="{{l.pos}}" title="{{l.name}}" id="{{l.id}}">
</marker>
<shape name="circle" stroke-color='#FF0000' stroke-weight="2" center="{{center}}" radius="{{radius}}" >
</shape>
</ng-map>
</div>

ng-map cluster with infowindow

I'm trying to display infowindow on clusters. My problem is that the infowindow is display far than the cluster and not on it.
This is how I have added the click event to the cluster:
$scope.markerCluster = new MarkerClusterer(map, markers);
google.maps.event.addListener($scope.markerCluster, 'clusterclick', function(cluster) {
$scope.map.showInfoWindow('bar', $scope.markerCluster);
console.log("cluster click");
});
To position info window over marker cluster setPosition function needs to be explicitly invoked, for example:
google.maps.event.addListener($scope.markerCluster, 'clusterclick', function (cluster) {
var infoWindow = $scope.map.infoWindows["myInfoWindow"]; //get infoWindow instance
infoWindow.setPosition(cluster.getCenter()); //<-set position
$scope.map.showInfoWindow('myInfoWindow', cluster);
});
Example
angular.module('mapApp', ['ngMap'])
.controller('mapController', function ($scope, NgMap) {
NgMap.getMap().then(function (map) {
$scope.map = map;
$scope.initMarkerClusterer();
});
$scope.cities = [
{ id: 1, name: 'Oslo', pos: [59.923043, 10.752839] },
{ id: 2, name: 'Stockholm', pos: [59.339025, 18.065818] },
{ id: 3, name: 'Copenhagen', pos: [55.675507, 12.574227] },
{ id: 4, name: 'Berlin', pos: [52.521248, 13.399038] },
{ id: 5, name: 'Paris', pos: [48.856127, 2.346525] }
];
$scope.initMarkerClusterer = function () {
var markers = $scope.cities.map(function (city) {
return $scope.createMarker(city);
});
var mcOptions = { imagePath: 'https://cdn.rawgit.com/googlemaps/js-marker-clusterer/gh-pages/images/m' , zoomOnClick: false };
$scope.markerCluster = new MarkerClusterer($scope.map, markers, mcOptions);
google.maps.event.addListener($scope.markerCluster, 'clusterclick', function (cluster) {
//generate infoWindow content
var cities = cluster.getMarkers().map(function(m){
return m.title;
});
$scope.content = cities.join(",");
var infoWindow = $scope.map.infoWindows["myInfoWindow"]; //get infoWindow instance
infoWindow.setPosition(cluster.getCenter());
$scope.map.showInfoWindow('myInfoWindow', cluster);
});
};
$scope.createMarker = function (city) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(city.pos[0], city.pos[1]),
title: city.name
});
google.maps.event.addListener(marker, 'click', function () {
$scope.content = marker.title;
$scope.map.showInfoWindow('myInfoWindow', this);
});
return marker;
}
});
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/scripts/ng-map.js"></script>
<script src="https://googlemaps.github.io/js-marker-clusterer/src/markerclusterer.js"></script>
<div ng-app="mapApp" ng-controller="mapController">
<ng-map default-style="true" zoom="3" center="59.339025, 18.065818">
<info-window id="myInfoWindow">
<div ng-non-bindable>
<h4>{{content}}</h4>
</div>
</info-window>
</ng-map>
</div>

ng-repeat not copying correctly over

I have ng-repeat working within a different template, however, I can not get my album.html template to display content. Here is what I have.
app.js
...
.state('album', {
url: '/album',
controller: 'AlbumCtrl as album',
templateUrl: '/templates/album.html'
})
...
AlbumCtrl.js
(function() {
function AlbumCtrl() {
this.albumData = angular.copy(albumPicasso);
};
angular
.module('blocJams')
.controller('AlbumCtrl', AlbumCtrl);
})();
fixture.js (where my object I want to copy lives)
var albumPicasso = {
title: 'The Colors',
artist: 'Pablo Picasso',
label: 'Cubism',
year: '1881',
albumArtUrl: 'assets/images/album_covers/01.png',
songs: [
{ title: 'Blue', duration: 161.71, audioUrl: 'assets/music/bloc_jams_music/blue' },
{ title: 'Green', duration: 103.96, audioUrl: 'assets/music/bloc_jams_music/green' },
{ title: 'Red', duration: 268.45, audioUrl: 'assets/music/bloc_jams_music/red' },
{ title: 'Pink', duration: 153.14, audioUrl: 'assets/music/bloc_jams_music/pink' },
{ title: 'Magenta', duration: 374.22, audioUrl: 'assets/music/bloc_jams_music/magenta' }
]
};
albumt.html (here is my template with ng-repeat)
<main class="album-view container narrow">
<section class="clearfix">
<div class="column half">
<img src="/assets/images/album_covers/01.png" class="album-cover-art">
</div>
<div class="album-view-details column half">
<h2 class="album-view-title">The Colors</h2>
<h3 class="album-view-artist">Pablo Picasso</h3>
<h5 class="album-view-release-info">1909 Spanish Records</h5>
</div>
</section>
<table class="album-view-song-list">
<tr class="album-view-song-item" ng-repeat="album in album.albumData" ng-mouseover="hovered = true" ng-mouseleave="hovered = false">
<td class="song-item-number">
<span ng-show="!playing && !hovered"></span>
<a class="album-song-button" ng-show="!playing && hovered"><span class="ion-play"></span></a>
<a class="album-song-button" ng-show="playing"><span class="ion-paused"></span></a>
</td>
<td class="song-item-title">{{ album.songs.title }}</td>
<td class="song-item-duration">{{ album.songs.duration }}</td>
</tr>
</table>
</main>
<ng-include src="'/templates/player_bar.html'"></ng-include>
{{ album.songs.title }} and {{ album.songs.duration }} isn't displaying any content nor am I receiving any errors. I personally believe I am not copying my object through my controller correctly? Further, how can I see my input of said object through my controller to test whether my object albumPicasso was copied correctly?
For Reference
This controller (CollectionCtrl.js) is working correctly and mirrors what I want to do besides the for loop.
(function() {
function CollectionCtrl() {
this.albums = [];
for (var i=0; i < 12; i++) {
this.albums.push(angular.copy(albumPicasso));
}
}
angular
.module('blocJams')
.controller('CollectionCtrl', CollectionCtrl);
})();
album in album.albumData
May be you want to not override album variable name?
Controller alias is just variable in scope. You are overwriting it.
It looks like:
for (var i = 0; i < album.albumData.length; i++) {
album = album.albumData[i]; // <-- We brake all things here
}
Just rename album in ngRepeat to something like item:
ng-repeat="item in album.albumData"
Also, you want iterate a songs array, not an object:
ng-repeat="song in album.albumData.songs"
and
{{song.title}}
albumPicasso doesn't seem to be a global variable so it seems it's not accessible from AlbumCtrl.js. Try setting this.albumData to some dummy data.
I would personally create an angular service that provides the album data and inject it in the controller.
you can create a service for this
(function() {
var albumPicasso = {
title: 'The Colors',
artist: 'Pablo Picasso',
label: 'Cubism',
year: '1881',
albumArtUrl: 'assets/images/album_covers/01.png',
songs: [{
title: 'Blue',
duration: 161.71,
audioUrl: 'assets/music/bloc_jams_music/blue'
}, {
title: 'Green',
duration: 103.96,
audioUrl: 'assets/music/bloc_jams_music/green'
}, {
title: 'Red',
duration: 268.45,
audioUrl: 'assets/music/bloc_jams_music/red'
}, {
title: 'Pink',
duration: 153.14,
audioUrl: 'assets/music/bloc_jams_music/pink'
}, {
title: 'Magenta',
duration: 374.22,
audioUrl: 'assets/music/bloc_jams_music/magenta'
}]
};
function fixtureService() {
this.getAlbumData = function(){
return albumPicasso;
};
}
angular
.module('myApp')
.service('fixtureService', fixtureService);
})();
and this service can be injected into your controller
(function() {
function AlbumController(fixtureService) {
this.albumData = fixtureService.getAlbumData();
console.log(this.albumData);
}
angular
.module('myApp')
.controller('AlbumController',['fixtureService', AlbumController]);
})();

Angular Google Maps Polyline Coordinates from Database

I am trying to display a Polyline on an Ionic application using Angular Google Maps with coordinates from a database. I read the documentation on the Angular Google Maps site regarding getting the coordinates and attempting to create the path via the coordinates from an API. I tried using Angular.forEach to use checklat and checklong as my coordinates but it doesn't show anything on the map. How can I use the coordinates on the data below to display as a polyline?
Data from API:
_id "57393e042613d90300a35a0a"
tripstatus "1"
tripcreated "1463367863236"
tripdescription "testing one two three. i am ironman."
tripname "New trip to test user current trip"
__v 0
checks
0 checklat " 10.72403187357376"
checklong "122.53443290985284"
time "1463367863236"
_id "57394ae62613d90300a35a10"
1 checklat "10.724010661667863"
checklong "122.53442867631733"
time "1463367863236"
_id "57394b272613d90300a35a16"
2 checklat "10.6817828"
checklong "122.5389465"
time "1463367863236"
_id "57394c662613d90300a35a1a"
My Controller:
TripFac.getTrip(id).success(function(data) {
$scope.trips = data;
var latlng = data[0].checks;
angular.forEach(latlng, function(path) {
path = {
latitude: checklat,
longitude: checklong
}
});
$scope.latlng = latlng;
});
//Get Trip Points and put on polyline
$scope.polylines = [];
uiGmapGoogleMapApi.then(function(){
$scope.polylines = [
{
path: latlng,
stroke: {
color: '#6060FB',
weight: 3
},
geodesic: true,
visible: true,
icons: [{
icon: {
path: google.maps.SymbolPath.BACKWARD_OPEN_ARROW
},
offset: '25px',
repeat: '50px'
}]
}
];
});
My view:
<ui-gmap-google-map
center="map.center"
zoom="map.zoom"
id="wrapper">
<style>
.angular-google-map-container { height:450px; width:auto; }
</style>
<ui-gmap-polyline ng-repeat="p in polylines" path="p.path" stroke="p.stroke" visible='p.visible' geodesic='p.geodesic' fit="false" editable="p.editable" draggable="p.draggable" icons='p.icons'></ui-gmap-polyline>
</ui-gmap-google-map>
Foe example
$scope.map.center = {
latitude: $scope.latitude,
longitude: $scope.longitude
};
var directionsDisplay = new google.maps.DirectionsRenderer({
suppressMarkers: true
});
var directionsService = new google.maps.DirectionsService();
$scope.directions = {
origin: new google.maps.LatLng($scope.lat, $scope.lng),
destination: new google.maps.LatLng($scope.latitude, $scope.longitude),
showList: false
}
var request = {
origin: $scope.directions.origin,
destination: $scope.directions.destination,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status === google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
directionsDisplay.setMap($scope.map.control.getGMap());
} else {}
});
It could be related with one of the following reasons:
undefined latlng object is passed into $scope.polylines, needs to be changed to $scope.latlng
$scope.polylines could be initialized before json data is getting loaded
The following example demonstrates how to load data from external source and initialize a polygon(s) on the map:
angular.module('map-example', ['uiGmapgoogle-maps'])
.controller('MapController', function($scope, $http, uiGmapGoogleMapApi, uiGmapIsReady) {
$scope.map = {
zoom: 12,
bounds: {},
center: { latitude: 10.6817828, longitude: 122.53443290985284 }
};
var loadPathData = function() {
return $http.get('https://rawgit.com/vgrem/3fc4ffc90de778f38f09b671466001fa/raw/8da45ddf4b174d758892e8a6514fea9145f4b91b/data.json')
.then(function(res) {
//extract data
return res.data[0].checks.map(function(item) {
return {
latitude: item.checklat,
longitude: item.checklong
}
});
});
};
var drawPolylines = function(path) {
$scope.polylines = [
{
path: path,
stroke: {
color: '#6060FB',
weight: 3
},
geodesic: true,
visible: true,
icons: [{
icon: {
path: google.maps.SymbolPath.BACKWARD_OPEN_ARROW
},
offset: '25px',
repeat: '50px'
}]
}
];
}
uiGmapIsReady.promise()
.then(function(instances) {
loadPathData()
.then(drawPolylines);
});
});
.angular-google-map-container {
height: 450px;
width: auto;
}
<div ng-app="map-example" ng-controller="MapController">
<ui-gmap-google-map center="map.center" zoom="map.zoom" id="wrapper">
<ui-gmap-polyline ng-repeat="p in polylines" path="p.path" stroke="p.stroke" visible='p.visible' geodesic='p.geodesic' fit="false"
editable="p.editable" draggable="p.draggable" icons='p.icons'></ui-gmap-polyline>
</ui-gmap-google-map>
<script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.0.1/lodash.js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<script src="http://cdn.rawgit.com/nmccready/angular-simple-logger/0.0.1/dist/index.js"></script>
<script src="http://cdn.rawgit.com/angular-ui/angular-google-maps/master/dist/angular-google-maps.min.js"></script>
</div>

Repeating multidimensional array object in angular

I have an array that looks like this:
[Object{ 82893u82378237832={ id=8, no=1, type="event", name="Sample1"}}, Object{ 128129wq378237832={ id=9, no=1, type="event", name="Sample2"}} ]
Now ignoring the first part which is just a random token i want to get the array inside that. i.e. id,no,type,name and display them in an ng-repeat, how can i achieve this?
This is how i create the above array:
var obj = {};
obj[data.responseData] = {
id: 8,
no: 1,
type: 'event',
name: ''
}
$scope.items.push(obj);
Your example doesn't include an array.
Anyway here's a good example.
Use map to transform an array to another array and use ng-repeat in a similar way that I've done.
Html:
<div ng-app="app">
<div ng-controller="ctrl">
<div ng-repeat="item in myArr">
{{item}}
</div>
</div>
</div>
JS:
angular.module('app', []).
controller('ctrl', function ($scope) {
var arr = [{
myId: '82893u82378237832',
id: 8,
no: 1,
type: "event",
name: "Sample1"
}, {
myId: '128129wq378237832',
id: 9,
no: 1,
type: "event",
name: "Sample2"
}];
// mapped the new object without myId
$scope.myArr = arr.map(function (item) {
return {
id: item.id,
no: item.no,
type: item.type,
name: item.name
}
});
});
JSFIDDLE.

Resources