Is anyone familiar with NgMap directives for using the Google Maps API? I have gotten a map to render with markers on data points, however I want to zoom in when I click on the marker. This isn't working for me. I am just trying to log the passed in location of the marker and I am seeing nothing right now.
I'm pretty new to AngularJS so I am probably missing something with the scope. Thanks!
Here's the map:
<div id='map'>
<map center="{{ $ctrl.map.center.latitude }}, {{ $ctrl.map.center.longitude }}" zoom="{{ $ctrl.map.zoom }}">
<div ng-repeat="location in $ctrl.locations">
<marker position="[{{ location.latitude }}, {{ location.longitude }}]" ng-click="$ctrl.pinClicked(location)"></marker>
</div>
</map>
</div>
And the component:
angular.module('myplaces')
.component('placespage', {
templateUrl: 'places.template.html',
controller: controller
})
function controller(placeService, NgMap) {
const ctrl = this;
ctrl.locations = [];
ctrl.marker = []
ctrl.map = {}
var map;
ctrl.$onInit = function() {
placeService.getPlaces().then(function(response) {
console.log(response.data.rows);
ctrl.locations = response.data.rows;
})
NgMap.getMap().then(function(map) {
console.log(ctrl.map);
})
ctrl.map = {
center:
{
latitude: 34.8394,
longitude: 134.6939
},
zoom:5,
};
}
ctrl.pinClicked = function(loc) {
console.log(loc); //This is getting nothing...
ctrl.map.setZoom(8);
}
}
move ng-repeat to marker directive and use onClick to bind with controller's function.
<marker ng-repeat="location in $ctrl.locations" position="[{{ location.latitude }}, {{ location.longitude }}]" on-click="$ctrl.pinClicked(location)"></marker>
see sample here.
Related
I want to create a dashboard like feature on my existing angular app using Chart.js. So, I created a view for the dashboard.
<md-content layout-padding layout-fill flex class="animated fadeIn">
<div layout-padding>
<md-card-title>
<md-card-title-text>
<span class="md-headline">Dashboard</span>
</md-card-title-text>
</md-card-title>
</div>
<md-divider></md-divider>
<div>
<md-grid-list md-cols-gt-md="12" md-cols-sm="3" md-cols-md="8"
md-row-height-gt-md="1:1" md-row-height="4:3"
md-gutter-gt-md="8px" md-gutter-gt-sm="4px" md-gutter="2px">
<md-grid-tile md-colspan-gt-sm="3" md-rowspan-gt-sm="3">
<pie-chart header="'Auths'" auth-counts="ctrl.authCounts" flex-gt-sm></pie-chart>
</md-grid-tile>
</md-grid-list>
</div>
</md-content>
The dashboard controller is loaded from the route (ui.router). The controller is empty at the moment.
//router
.state('home.dashboard', {
url: '/dashboard',
controller: 'DashboardController as ctrl',
templateUrl: baseUrl + 'Scripts/src/views/dashboard/dashboard.home.html'
})
function DashboardController() {
var ctrl = this;
ctrl.$onInit = function () {
console.log('testing');
ctrl.authCounts = [800, 200];
}
}
Then, the component pie-chart looks like the following.
(function () {
'use strict';
angular.module('chart')
.component('pieChart', {
controller: PieChartComponentController,
templateUrl: 'Scripts/src/views/dashboard/pie.chart.template.html',
bindings: {
header: '<',
authCounts: '<'
}
});
PieChartComponentController.$inject = ['$timeout'];
function PieChartComponentController($timeout) {
var $ctrl = this;
$ctrl.$onInit = function () {
var myPieChart;
var data;
}
$ctrl.isArrayEmpty = function (authCount) {
if (!authCount) return true;
return authCount.length === 0;
}
$ctrl.createChart = function () {
var pieData = {
labels: ["Purple","Green","Orange","Yellow"],
datasets: [
{
data: [20, 40, 10, 30],
backgroundColor: ["#878BB6","#4ACAB4","#FF8153","#FFEA88"]
}
]
};
var ctx = document.getElementById("myPieChart").getContext("2d");
var myPieChart = new Chart(ctx, {
type: 'pie',
data: pieData
});
} // end createChart()
}
})();
And the pie-chart template looks like the following.
<div layout-align="start center" ng-if="$ctrl.isArrayEmpty($ctrl.authCounts)">
Not enough information available to create the chart.
</div>
<canvas id="myPieChart" width="250" height="250" ng-init="$ctrl.createChart()" ng-if="$ctrl.isArrayEmpty($ctrl.authCounts)" flex-gt-sm></canvas>
</md-card-content>
It seems like everything is fine, but the canvas height and width is 0 and the chart is not rendered.
However, if I remove the pie-chart component, and put the <canvas> element outside in the dashboard template and the data in the dashboard, it renders the chart. But that's not what I want to do, though. I need to have component for each type. So, what am I doing wrong that's causing this behavior?
I also tried angular-chart.js that showed the same behavior. If I put the <canvas> element in the dashboard template, it displays the chart but not from inside pie-chart element. I need help troubleshooting it. I'm definitely missing something here but can't figure out what. Is the canvas being rendered before the data is provided, or is there something going on that I'm overlooking (or oblivious about)?
Trying to get a app using angular-google-maps with:
- multiple markers via the markers directive
- a single infowindow via the window directive
I've been through the API and multiple closed issues / questions on the git-hub site but just can't get it working... :-/
jsfiddle
For simplicity, I'm declaring the markers manually (and they're displaying correctly):
$scope.markers = [
{
id: 0,
coords: {
latitude: 37.7749295,
longitude: -122.4194155
},
data: 'restaurant'
},
{
id: 1,
coords: {
latitude: 37.79,
longitude: -122.42
},
data: 'house'
},
{
id: 2,
coords: {
latitude: 37.77,
longitude: -122.41
},
data: 'hotel'
}
];
The html looks like:
<body ng-app="app">
<div class="angular-google-map-container" ng-controller="MainCtrl">
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="map.options" events="map.events" control="googlemap">
<ui-gmap-window coords="markers.coords" show="windowOptions.show" closeClick="closeClick()">
<div>Hello</div>
</ui-gmap-window>
<ui-gmap-markers models="markers" idkey="markers.id" coords="'coords'" click="'onClick'" events="markers.events" >
</ui-gmap-markers>
</ui-gmap-google-map>
</div>
</body>
I'm applying the onClick function to the markers array using this code
$scope.addMarkerClickFunction = function(markersArray){
angular.forEach(markersArray, function(value, key) {
value.onClick = function(){
$scope.onClick(value.data);
};
});
};
The marker click functions look like
$scope.windowOptions = {
show: false
};
$scope.onClick = function(data) {
$scope.windowOptions.show = !$scope.windowOptions.show;
console.log('$scope.windowOptions.show: ', $scope.windowOptions.show);
console.log('This is a ' + data);
};
$scope.closeClick = function() {
$scope.windowOptions.show = false;
};
The $scope.onClick() function seems to be working on marker click since the console outputs what is expected - and the $scope.windowOptions.show value toggles between true and false...
I'm thinking it's the way I've connected the window html to the controller arrays and functions ? Any help is appreciated.
P.S. The API documentation examples seem out of date since they don't use show in the example but rather options.visible to show and hide infowindows - but then all the issues / examples suggest using show instead ?
I know this is an old post.
However, these days I've been struggling myself trying to do this and, moreover, the jsfiddle of the accepted answer is broken and doesn't work with latest versions of angular-google-maps directive. So, I've decided to share a working plunker hoping it can help other people.
Plunker here
This version is rendering multiple markers but just one window. Only one window can be opened at the same time.
It's based on the advises of the official site FAQ Section: See How do I only open one window at a time?
html
<ui-gmap-google-map center="map.center" zoom="map.zoom">
<ui-gmap-window
show="map.window.show"
coords="map.window.model"
options="map.window.options"
closeClick="map.window.closeClick()"
templateUrl="'infowindow.tpl.html'"
templateParameter="map.window">
</ui-gmap-window>
<ui-gmap-markers
models="map.markers"
coords="'self'"
events="map.markersEvents"
options="'options'">
</ui-gmap-markers>
</ui-gmap-google-map>
js
$scope.map = {
center: {
latitude: 39.5925511,
longitude: 2.633202
},
zoom: 14,
markers: [], // Markers here
markersEvents: {
click: function(marker, eventName, model) {
$scope.map.window.model = model;
$scope.map.window.show = true;
}
},
window: {
marker: {},
show: false,
closeClick: function() {
this.show = false;
},
options: {}
}
};
Hope it helps.
Your marker's binding is incorrect in the window directive.
Basically, you need to set a marker as selected on click and bind the window to that selected marker. See the jsfiddle for a working example.
<body ng-app="app">
<div class="angular-google-map-container" ng-controller="MainCtrl">
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="map.options" events="map.events" control="googlemap">
<ui-gmap-window coords="MapOptions.markers.selected.coords" show="windowOptions.show" closeClick="closeClick()">
<div>Hello</div>
</ui-gmap-window>
<ui-gmap-markers models="markers" idkey="markers.id" coords="'coords'" click="'onClick'" events="markers.events" >
</ui-gmap-markers>
</ui-gmap-google-map>
</div>
http://jsfiddle.net/gqkmyjos/
I know this is old post, but I struggled with Angular Google Map, and solve issue when you open one window for markers. If you use ng-repeat and window for each one - no problems. But when you have a markers directive, and want to show only one window, then you have an issue - window places not above marker and you need change position a little. How to do it? Let me share my experience on that.
You just need to specify pixelOffset for windowoptions like that:
JS:
$scope.windowOptions = {
pixelOffset : {
height: -25,
width: 0
}
};
HTML:
<ui-gmap-window coords='selectedmarker.coords' show='true' options='windowOptions'>
#{{ selectedmarker.tagline }}
</ui-gmap-window>
That's it. Change height for your needs.
you're better setting the marker model on the scope on click something like this:
marker click callback:
$scope.onClick = function(marker) {
$scope.selectedMarker = marker.model;
}
Then use the selectedMarker in the directive:
<ui-gmap-window coords="selectedMarker" show="windowOptions.show" closeClick="closeClick()">
<div>Hello</div>
</ui-gmap-window>
simple. assumes your marker model has longitude and latitude set of cause
I am using the library angular-google-maps from http://angular-google-maps.org/. I am able to get most everything to work. What I am currently banging my head against is to get the "click" event to work on the map to give me the GEO location of where I clicked. Currently it's not even registering that I am clicking on the map.
Here is my partial:
<google-map
center="map.center"
zoom="map.zoom"
draggable='true'
>
</google-map>
and here is the controller:
// Create Map
$scope.map = {
center: {
latitude: 40.296755,
longitude: -111.696415
},
zoom: 13,
events: {
click: function (mapModel, eventName, originalEventArgs) {
alert("hola?");
}
}
};
Any help would be fantastic!
To add the event to the map, you need to attach an associative array (object) to the events attribute of the directive:
<google-map events="$scope.events" .... ></google-map>
In Controller:
$scope.events = {"click" : function () { console.log('woo-hoo') })
When I change my app from jQuery way to Angular way,
I try to use Angular-Google-Maps.
But I can't find where is the Google Map Objects(Map, Marker, Polygon...)
and the approach to use Object 'method' (such like getMap() , getPath(), getPosition()..).
If I need to get the position of the marker which is dragged, how can i do?
just like I usually do ?
marker = new google.maps.Marker(opts);
postion = marker.getPosition();
Edit:
I found a way how to get the marker position when it was dragged'n'dropped. You can set the callback function for the marker:
<google-map center="center" zoom="zoom" control="googleMap">
<marker coords="coords" options="options" events="events">
</google-map>
Then in the controller you define the callback:
$scope.events: {
dragend: function (marker) {
$rootScope.$apply(function () {
console.log(marker.position.lat());
console.log(marker.position.lng());
});
}
}
Old Answer:
It is currently not possible:
https://github.com/nlaplante/angular-google-maps/issues/277
However, you can get the original google.maps.Map object:
Directive call:
<google-map center="center" zoom="zoom" control="googleMap"></google-map>
Angular controller:
...
$scope.center = = {
latitude: 48.13171,
longitude: 11.549554
};
$scope.zoom = 8;
$scope.googleMap = {}; // this is filled when google map is initiated
function getMapObject() {
$scope.googleMap.control.getGMap();
}
...
Actually you don't even need events, the library already binds your marker position with the scope.
Here is how I did it in Coffee Script:
Controller:
$scope.map =
center:
latitude: k
longitude: D
zoom: 16
marker:
coord:
k
D
View:
<ui-gmap-google-map center='map.center' zoom='map.zoom'>
<ui-gmap-marker
idKey="'pin'"
coords="map.marker.coord"
options="{'draggable':true}"
>
</ui-gmap-marker>
</ui-gmap-google-map>
<pre>{{map | json}}</pre>
I have this problem where I am trying to make a click on a div hide all the other divs of the same "kind". Basically I'd have to, from a child scope set the variable on all other "sibling" scopes.
To illustrate this, I have created the following:
HTML
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<div ng-repeat="model in models" ng-controller="MyChildCtrl">
<a ng-click="toggleVisibility()">toggle {{ model.name }} {{ visibility }}</a>
<div ng-show="visibility">
{{ model.name }}
</div>
</div>
</div>
</div>
JavaScript
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
console.debug('scope');
$scope.models = [
{ name: 'Felipe', age: 30 },
{ name: 'Fernanda', age: 28 },
{ name: 'Anderson', age: 18 }
];
}
function MyChildCtrl($scope) {
$scope.visibility = false;
$scope.toggleVisibility = function() {
$scope.visibility = !$scope.visibility;
}
}
JSFiddle: http://jsfiddle.net/fcoury/sxAxh/4/
I'd like that, every time I show one of the divs, that all other divs would close, except the clicked one.
Any ideas?
#kolrie while your approach works I would suggest a different solution which doesn't require any changes to the model. The basic idea is to keep a reference to a selected item and calculate viability by comparing a current item (inside ng-repeat) with a selected one.
Using this solution the toggle function would become:
$scope.toggleVisibility = function(model) {
$scope.selected = model;
};
and calculating visibility is as simple as:
$scope.isVisible = function(model) {
return $scope.selected === model;
};
Finally the relevant part of the markup is to be modified as follows:
<div ng-controller="MyCtrl">
<div ng-repeat="model in models">
<a ng-click="toggleVisibility(model)">toggle {{ model.name }} {{ isVisible(model) }}</a>
<div ng-show="isVisible(model)">
{{ model.name }}
</div>
</div>
</div>
Here is a complete jsFiddle: http://jsfiddle.net/XfsPp/
In this solution you can keep your model untouched (important if you want to persist it back easily) and have AngularJS do all the heavy-lifting.
OK, I have added a visible attribute to the model, and I managed to get this done:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
console.debug('scope');
$scope.models = [
{ name: 'Felipe', age: 30, visible: false },
{ name: 'Fernanda', age: 28, visible: false },
{ name: 'Anderson', age: 18, visible: false }
];
}
function MyChildCtrl($scope) {
$scope.toggleVisibility = function() {
angular.forEach($scope.models, function(model) {
model.visible = false;
});
$scope.model.visible = true;
}
}
Live here: http://jsfiddle.net/fcoury/sxAxh/5/
Is this the most efficient way? Do you think it's a good practice if I inject this visible attribute into my model data after getting it via AJAX?