I have a question about angular leaflet directive customized popup using compile template.
I am using ionic 1.2.4, angular leaflet directive 0.10.0 and leaflet 1.0.0rc-1.
In the controller, I wrote the following code.
var marker = {
type: markerType,
lat: myLatlng[0],
lng: myLatlng[1],
id: id,
getMessageScope: function () { return $scope; },
message: "<a ng-click=\"alert()\">howdy</a>",
compileMessage: true
};
$scope.markersArray.push(marker);
$scope.alert = function(){
console.log("hahahahaha[");
}
Here is the fiddle link: http://jsfiddle.net/caiczcz/m7g8Le0L/1/
Although the link is presented in the popup, but the click event is never triggered, I think that the problem might come from the compile process. Any advice is appreciated. THX.
In Angular-leaflet-directive,
$timeout(function(){
$compile(marker._popup._contentNode)(markerScope);
});
this will introduce a flicker issue, which can be resolved by adding a timeout to the popup's showing up or adding some animation, .etc.
Related
I want to let a user click a button, to show the draw controls on a map. Once a circle, marker etc has been added, the draw controls are hidden again.
I am building an Angular app and I am using the NgMap directive (https://ngmap.github.io/)
My example code looks like this:
html:
<ng-map id="myMap">
<drawing-manager
on-overlaycomplete="ctrl.onMapOverlayCompleted()"
drawingControl="ctrl.showDrawControl">
</drawing-manager>
</ng-map>
Controller:
vm.showDrawControl = true;
NgMap.getMap({ id: 'myMap' }).then(function (map) {
vm.onMapOverlayCompleted = function (event) {
vm.showDrawControl = false;
alert(vm.showDrawControl);
}
});
The function is called on overlayComplete, but the controls are not hidden?
Examining the source code of ng-map I've seen that the observer to drawingControl attribute is missing, so it can't be updated after initial setup using Angular binding.
Two alternatives to resolve the issue:
1) patching ng-map.js adding the following code to drawingManager directive:
attrs.$observe('drawingcontrol', function (newValue) {
drawingManager.setOptions({
drawingControl: (newValue=="true" ? true : false)
});
});
2) using directly Google maps API as stated here
map.mapDrawingManager[0].setOptions({drawingControl:false/true})
Check my plunker for option 2:
http://plnkr.co/edit/KUCMVdgRZ3TsN9P0FlZR
P.S.: in the Plunker above you can see also a patched version of ng-map (however not used but tested as working).
I am building an application using Semantic UI and ReactJS. I am using a tab module to contain my map, which uses the Leaflet Javascript library to render the map.
The problem is that the tiles do not display correctly until the page is resized.
The is what I have tried:
MapComponent = React.createClass({
componentDidMount() {
let map = L.map('map')
L.tileLayer.provider('Thunderforest.Outdoors').addTo(map)
map.setView([lat, long], zoom)
map.invalidateSize(false)
}
}
Which did not seem to fix the problem.
I tried setting a timeout, like so:
MapComponent = React.createClass({
componentDidMount() {
let map = L.map('map')
L.tileLayer.provider('Thunderforest.Outdoors').addTo(map)
Meteor.setTimeout(() => {
map.invalidateSize(false)
}, 2000)
map.setView([lat, long], zoom)
}
})
Which sometimes worked by setting the timer to 2000, but sometimes it needed to be set to 5000, which is a bit crazy in my opinion.
From what I have read, calling the invalidateSize() function should fix the problem. Any help solving this problem would be greatly appreciated. Thank you.
Call invalidateSize once the tab containing your map becomes visible. In Semantic UI's tab module you can do that by using the onVisible callback:
Called after a tab becomes visible
http://semantic-ui.com/modules/tab.html#/settings
<div class="ui menu top">
<a class="item" data-tab="map">Map</a>
</div>
$('.top.menu .item').tab({
'onVisible': function () {
// Do stuff
}
});
I have already read all the posts about this, but unfortunately none of them was helpful: jsfiddle and plunker links appear to be no longer working.
What I am trying to do is to simply put a button inside the bootstrap pop-over which makes a call to a function inside the scope of the directive I've created. The problem is that using jquery to grab the content it does not work since the scope appear to be outside. Also trying to create the content inside the function it won't work because it will be not compiled.
I created an example on jsfiddle, but somehow angularjs is not loaded in the right point and therefore it doesn't work either.
$("#pop-over-link").popover({
'placement': 'top',
'trigger': 'click',
'html': true,
'container': 'body',
'content': function() {
return $("#pop-over-content").html();
}
});
This is the piece of code that opens the pop over, grabs the contents and shows it.
Here the jsfiddle: http://jsfiddle.net/75zLT/2/
And here is the working example on my dropbox: https://dl.dropboxusercontent.com/u/19470623/hatethis/test.html
There were 2 issues your were not including ngRoute in your fiddle and your need to compile the content returned in the popover.
'content': function() {
return $compile($("#pop-over-content").html())(scope);
}
Also you do not need the timeout.
Example: Plunker
http://plnkr.co/edit/GRVZl35D1cuWz1kzXZfF?p=preview
In the custom fancybox (aka lightbox, a dialog) I show contents with interpolated values.
in the service, in the "open" fancybox method, i do
open: function(html, $scope) {
var el = angular.element(html);
$compile(el)($scope); // how to know when the $compile is over?
$.fancybox.open(el); // the uncompiled is shown before the compiled
}
The problem is that the content in the dialog is loaded before the end of the $compile, so after less than a second i got a refresh of the dialog content with the values.
The plunkr works, but i want to avoid that the "el" is shown before it gets totally compiled: i want to show it only after the $compile has finished his job
Is there a way to know when the $compile it's over so i'll show the content on fancybox only after that?
You can't inject $scope into services, there is nothing like a singleton $scope.
So instead of $compile(el)($scope); try:
var compiledEl = $compile(el);
....
The $compile returns compiled data.
as a side note
I would provide service to directive and compile it into directive instead. I think it's the right way.
I've had the same problem with the ngDialog modals and popup provider. I needed to position the dialog based on its height. But the height depended on the compiled DOM.
I eventually found a solution using $timeout, like described in that post: http://blog.brunoscopelliti.com/run-a-directive-after-the-dom-has-finished-rendering/
For your code, it would give something like that:
open: function(html, $scope) {
var el = angular.element(html);
$compile(el)($scope);
$timeout(function() {
$.fancybox.open(el);
}, 0);
}
The ui-map example works perfectly when using on a simple angular.js page.
Now I'm using the ui-router and trying to display the map inside a view.
What happens is that the map tiles are only displayed on half of the map.
If I resize the window, the map is displayed correctly.
I think I have to trigger the Google Maps resize event once the view is rendered, but how?
google.maps.event.trigger(<myMapObject>, 'resize');
Wait for a while before calling trigger, I had this same issue and found resolved here:
AngularJS: map via Google Maps API v3 in a tab
window.setTimeout(function(){
google.maps.event.trigger(map, 'resize');
},100);
that work with angular 1.3.15
$timeout(function(){
angular.forEach($scope.maps, function(index) {
google.maps.event.trigger(index, 'resize');
});
}, 100);
}
$scope.maps = [];
$scope.$on('mapInitialized', function(evt, evtMap) {
$scope.maps.push(evtMap);
});
http://plnkr.co/edit/3P4iLTrog1ismFDUQNQe?p=preview
other solutions
without adding $timeout you could also use $scope.$applyAsync() that runs code within the same digest cycle