Angular Maps DrawManager instance in Custom Control - javascript

I having the diffuculty to create a custom control in order to change drawMode of the map in the Angular Google Maps library.
My markup is this
<ui-gmap-google-map id="map" center="map.center" pan="map.pan" zoom="map.zoom" draggable="true" refresh="map.refresh" options="map.options" events="map.events" bounds="map.bounds" dorebuildall="true">
<ui-gmap-map-control template="js/app/templates/mapToolbar.tpl.html" position="top-right" controller="mapWidgetCtrl"></ui-gmap-map-control>
<ui-gmap-polygons models="map.polygons" clickable="true" draggable="true" editable="true" dorebuildall="true"></ui-gmap-polygons>
<ui-gmap-markers models="mapMarkers" coords="'self'" icon="'icon'" events="clickEventsObject"></ui-gmap-markers>
<ui-gmap-drawing-manager options="drawingManagerOptions" control="drawingManagerControl" events="drawEventHandler"></ui-gmap-drawing-manager>
</ui-gmap-google-map>
And my controllers are these (writing most relevant parts of code)
app.controller('mapSearchCtrl', ["$scope", "$http", function ($scope, $http) {
$scope.map = {
center: {
latitude: 40,
longitude: 20
},
zoom: 9,
bounds: {},
polygons: {},
options: {
panControl: false,
zoomControl: true,
zoomControlOptions: {
position: google.maps.ControlPosition.RIGHT_BOTTOM
},
mapTypeControl: false,
disableDefaultUI: true
}
};
$scope.drawingManagerOptions = {
drawingMode: null,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYGON,
]
},
polygonOptions: {
strokeWeight: 3,
editable: true
}
};
$scope.drawingManagerControl = {};
$scope.options = {};
$scope.mapMarkers = [];
$scope.clickEventsObject = {
mouseover: markerMouseOver,
mouseout: markerMouseOut
};
$scope.drawEventHandler = {
polygoncomplete: polygonComplete
};
function polygonComplete(drawingManager, eventName, scope, args) {
//$scope.drawingManagerControl.getDrawingManager().setDrawingMode(null); works here
//code...
});
[etc]..
And the other controller for the template with custom controls is:
app.controller('mapWidgetCtrl', ['$scope', function ($scope) {
$scope.toogleMap = function() {
console.log('Change map view via drawingManager');
};
}]);
I am having a difficutly into changing map view manually in both controllers (can't pass it somehow from one to another either). It seems I can't find a way to get the instance of drawManager outside of anything except polygonComplete function.
Any advice would be helpful, thank you.

You could introduce a service to share Drawing Manager Control across controllers:
app.service('sharedMapProperties', function () {
var drawingManagerControl = {};
return {
setDrawingManagerControl: function (value) {
drawingManagerControl = value;
},
getDrawingManagerControl: function () {
return drawingManagerControl;
}
}
});
Now you could save the control (drawingManagerControl variable) once the map is initialized:
app.controller('mapSearchCtrl', function ($scope, uiGmapIsReady, sharedMapProperties) {
//the remaining code is omitted..
$scope.drawingManagerControl = {};
sharedMapProperties.setDrawingManagerControl($scope.drawingManagerControl);
});
and then get control once the button clicked:
app.controller('mapWidgetCtrl', ['$scope', 'sharedMapProperties', function ($scope, sharedMapProperties) {
$scope.toogleMap = function () {
var control = sharedMapProperties.getDrawingManagerControl();
var drawingManager = control.getDrawingManager();
drawingManager.setDrawingMode(google.maps.drawing.OverlayType.CIRCLE);
console.log('Change map view via drawingManager');
};
}]);
Working example

Related

Cannot set property 'opacity' of undefined in gmap-window

getting following error as Cannot set property 'opacity' of undefined
HTML and Js as following
<ui-gmap-window show="map.infoWindow.show" coords="map.infoWindow.center" options="map.infoWindow.options"></ui-gmap-window>
$scope.map.infoWindow.options.content = "<h1>....<div>....</div></h1>";
and got the root cause
we should not use content obj inside the infoWindow Options from
AngularJS Google Map Directive - Error while displaying InfoWindow on Marker Click event
So tried from above stack
<ui-gmap-window show="map.infoWindow.show" coords="map.infoWindow.center" options="map.infoWindow.options">
{{ infoWindowContent }}
</ui-gmap-window>
$scope.infoWindowContent = "<h1>....<div>....</div></h1>";
Here, able to solve that console error. but html is not rendering. Showing Plain html string( Not converting into DOM )
Is there any way to solve this issue?
Since ng-bind-html directive does not seem to work properly with google.maps.InfoWindow, for example setting content property ui-gmap-window directive:
<ui-gmap-window show="infoWindow.show" coords='infoWindow.coords'>
<div ng-bind-html="{{infoWindow.content}}"></div>
</ui-gmap-window>
will cause the error that you have experienced.
But you could consider to introduce a custom directive to display InfoWindow content as html:
.directive('toHtml', ['$compile', function ($compile) {
return {
restrict: 'A',
link: function link($scope, $element, attrs) {
attrs.$observe('toHtml', function (value) {
if (value.length > 0) {
var $el = $compile(value)($scope);
$element.empty().append($el)
}
})
}
}
}])
and then bind html content:
<ui-gmap-window show="infoWindow.show" coords='infoWindow.coords'>
<div to-html="{{infoWindow.content}}"></div>
</ui-gmap-window>
Example
angular.module('MapApp', ['uiGmapgoogle-maps'])
.directive('toHtml', ['$compile', function ($compile) {
return {
restrict: 'A',
link: function link($scope, $element, attrs) {
attrs.$observe('toHtml', function (value) {
if (value.length > 0) {
var $el = $compile(value)($scope);
$element.empty().append($el)
}
})
}
}
}])
.controller('MapCtrl', function ($scope, uiGmapGoogleMapApi, uiGmapIsReady) {
$scope.map = {
zoom: 4,
bounds: {},
center: {
latitude: 40.1451,
longitude: -99.6680
},
options: {}
};
$scope.infoWindow = {
show: false,
content: '',
coords: {}
};
$scope.markers = [
{
latitude: 40.705565,
longitude: -74.1180857,
title: "New York",
id: 1,
},
{
latitude: 37.7576948,
longitude: -122.4726193,
title: "San Fransisco",
id: 2,
}
];
uiGmapGoogleMapApi.then(function (maps) {
$scope.showInfoWindow = function (marker, eventName, model) {
$scope.infoWindow.coords.latitude = model.latitude;
$scope.infoWindow.coords.longitude = model.longitude;
$scope.infoWindow.content = "<h2>" + model.title + "</h2>";
$scope.infoWindow.show = true;
};
$scope.closeInfoWindow = function () {
$scope.infoWindow.show = false;
};
});
});
.angular-google-map-container {
height: 30em;
}
<script src="https://code.angularjs.org/1.3.14/angular.js"></script>
<script src="https://rawgit.com/nmccready/angular-simple-logger/master/dist/angular-simple-logger.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-google-maps/2.2.1/angular-google-maps.js"></script>
<div ng-app="MapApp" ng-controller="MapCtrl">
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="false" options="map.options" bounds="map.bounds">
<ui-gmap-window show="infoWindow.show" coords='infoWindow.coords' closeClick="closeInfoWindow()">
<div to-html="{{infoWindow.content}}"></div>
</ui-gmap-window>
<ui-gmap-markers models="markers" coords="'self'" options="'options'" click="showInfoWindow">
</ui-gmap-markers>
</ui-gmap-google-map>
</div>

Angular google maps: put image in Info window

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!

When clicking cluster, how to show Infowindow which has markers's values?

I have been trying to use google map with angularJS.
I have learned how to use it through https://angular-ui.github.io/angular-google-maps/#!/.
Everything goes well.
For each marker, I can show InfoWindow which has an element information of myList.
But I have got stuck in InfoWindow with cluster.
When cluster is clicked, I want to show the information list of markers in cluster.
Even I can't show simple InforWindow when clicking the cluster.
Below sources are my code.
Please tell me if it is not enough to solve my problem.
Please tell me what is wrong and how to solve this.
Have a nice day.
* javascript
$scope.map.map = {
center: { latitude: $scope.map.myList[0].lat, longitude: $scope.map.myList[0].lng },
zoom: 17,
events : {
tilesloaded: function (map) {
$scope.$apply(function () {
google.maps.event.addDomListener(window, 'resize', function() {
var lat = $scope.map.myList[$scope.map.markerPosition-1].lat;
var lng = $scope.map.myList[$scope.map.markerPosition-1].lng;
var center = new google.maps.LatLng(lat, lng);
map.setCenter(center);
});
});
}
},
markersEvents: {
click: function(marker, eventName, model) {
model.show = !model.show;
return;
}
},
clusterOptions : { // options of cluster
gridSize: 40,
ignoreHidden: true,
zoomOnClick : false,
averageCenter : true,
styles: [
{
height: 53,
url: "http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/images/m3.png",
width: 53,
textColor : 'white'
}
]
},
clusterEvent: { // when cluster's clicked
click: function(map, markers) {
var contentString = 'ABCD';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
infowindow.open(map, markers);
return;
}
}
};
$scope.map.options = {
streetViewControl : false
};
$scope.map.markers = [];
* html
<ui-gmap-google-map center='map.map.center' zoom="map.map.zoom" options="map.options" events="map.map.events">
<ui-gmap-markers models="map.markers" coords="'self'" icon="a" events="map.map.markersEvents" options="'options'"
doCluster="true" clusterOptions="map.map.clusterOptions" clusterEvents="map.map.clusterEvent">
<ui-gmap-windows show="show">
<div ng-non-bindable>{{id}}</div>
</ui-gmap-windows>
</ui-gmap-markers>
Answer myself.
var infoWindowOptions = {
content: "asdfasdf"
};
var infowindow = new google.maps.InfoWindow(infoWindowOptions);
infowindow.open(map.map_, *marker*);

Mapbox map already initialized

I have an Angular service function to build a mapbox map like so:
app.service("MapService", [function(){
//mapbox vars
var map = {
minZoom: 11,
id: "xxxxxxxx",
token: "xxxxxxxx"
};
//build map
this.buildMap = function(lat, lon, zoom){
//map bounds
var southWest = L.latLng(54.04407014753034, -0.745697021484375),
northEast = L.latLng(53.45698455620496, -2.355194091796875),
bounds = L.latLngBounds(southWest, northEast);
//build map object
L.mapbox.accessToken = map.token;
map.obj = L.mapbox.map("map", map.id, {
maxBounds: bounds,
zoomControl: false,
minZoom: map.minZoom,
attributionControl: false
}).setView([lat, lon], zoom, {
pan: { animate: true },
zoom: { animate: true }
});
}
}]);
This simply populates a div:
<div id="map"></div>
When I go to a new Angular view and call this function again (to populate a new div with id map with the map) it gives me the error:
Map container is already initialized
How do I solve this problem?
You have to destroy the map before reinitializing it. Use the following
if(map.obj != undefined) map.obj.remove();
before
map.obj = L.mapbox.map("map", map.id, {
Using a directive is much more suitable for this kind of purpose, you won't run into stuff like this. In the following directive i'm using Leaflet, but it's just the same as using Mapbox (Mapbox is an extended version of Leaflet):
angular.module('app').directive('leaflet', [
function () {
return {
restrict: 'EA',
replace: true,
template: '<div></div>',
link: function (scope, element, attributes) {
scope.$emit('leaflet-ready', new L.Map(element[0]));
}
};
}
]);
Use it in your view:
<leaflet></leaflet>
Controller:
angular.module('app').controller('map1Controller', function($scope) {
$scope.$on('leaflet-ready', function (e, leaflet) {
// leaflet var contains map instance, do stuff
})
});
Here's an example of the concept: http://plnkr.co/edit/SFgGhVUtBOqsIwYuwNuv?p=preview

$http angularJS loop for each object with leaflet issue

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
};
}

Categories