6

I am trying to create a page with tabs (using AngularJS). There is a map (Google Maps API v3) in one of those tabs. When the map is in the tab in foreground everything seems to be OK. But when the map is loaded in the background tab and visible only after the tab is clicked the map is misplaced/cut off and when you try to manipulate with it it's functionality seems to be broken.

I've searched for solutions and I found those tricks with

google.maps.event.trigger(map, 'resize');
map.setCenter(center);

but it's not working. Could you please have a look at http://jsfiddle.net/n4q7Y/5/ and tell me what I missed?

Thank you.

HonzaBé
  • 752
  • 1
  • 16
  • 26

2 Answers2

7

Wait a moment before you trigger the resize-event: http://jsfiddle.net/doktormolle/aAeZw/

Dr.Molle
  • 116,463
  • 16
  • 195
  • 201
  • Nice, thank you:-) This fiddle updated with your idea also loads the marker: http://jsfiddle.net/honzzz/n4q7Y/22/ – HonzaBé Jan 21 '13 at 19:46
  • Dr.Molle, any idea why this is necessary? Seems like a hack just to bypass a flaw with the Maps module that results in two `$scope.$apply`s happening at the same time... Which should therefore be fixed in the module rather than with a timeout.. – Matty J May 29 '13 at 07:47
  • 1
    I guess the issue is the fact that changes on the selected-property are observed by 2 parties(1. forced by `$scope.$watch` and 2. by `ng-show` ), but there is no way to control the order of the call of the listeners, because they are called asynchronously. A better solution may be to set another property that indicates that the map will be shown and watch this property to trigger the resize-event for the map: http://jsfiddle.net/doktormolle/6WxtE/ – Dr.Molle May 29 '13 at 14:12
  • 1
    No, no, **NO**!!! Why do people keep accepting nonsense like this? A timer is A Bad Thing! If it is too short, then it will not work, if too long then the user will see some ugliness before it expires. Correct design is to wait for an event - always! I would suggest `tilesloaded` – Mawg says reinstate Monica May 10 '14 at 11:58
  • 1
    @Mawg: There is a minor pitfall with your awesome suggestion: It doesn't work. There isn't any map-event that fires when you select the tab: http://jsfiddle.net/doktormolle/2MEYq/ I wonder how you can give such an comment and ask 1 hour later [a similar question](http://stackoverflow.com/questions/23581001/how-to-tell-when-google-map-is-fully-loaded) – Dr.Molle May 10 '14 at 15:02
  • 1
    @Dr.Molle +1 I come in peace, so let us try to find a solution, not a flame war. I have spent 30+ years developing FSMs and have to state (grin) that everything should be event driven. Timers should only be users as a guard - to indicate thatthe expected event has not arrived. Is there any error in my staement that "if the timer is too short, then it will not work, if too long then the user will see some ugliness before it expires"? So, we have to look for an event driven solution (which explains why I asked a question seeeking an event (not timer) driven solution) soon afterwards. – Mawg says reinstate Monica May 11 '14 at 08:07
  • I am not 100% certain that a tab related event is the answer. Perhaps map related is? Even if the tab is "in the background", I _think_ (being an Angular n00b) that the map is still loading & receveing events. Any solutions which is not based on an "map fully loaded" event is dirty & prone to failure. Can we try to find one together? If you can find such an answer to my question, I will award a bounty. Thanks – Mawg says reinstate Monica May 11 '14 at 08:11
3

thank you Dr.Molle, if I can improve it a bit, in my case a $timeout without delay do the job perfectly (as it gonna wait until the end of the $digest cycle)

$timeout(function () {
    // in my case
    initializeMap();
    // OR this case:
    google.maps.event.trigger(map, 'resize');                      
}, 1000); // with or without delay
Sebastien Horin
  • 10,803
  • 4
  • 52
  • 54
  • Hey @Zeev G, isn't It working without the delay? $timeout without delay is a trick to wait angular is ready. (But it's possible Google Map is loaded asynchronously so it could be slower than angular) – Sebastien Horin Jul 28 '16 at 12:39