Chanon Deeprasertkul
Chanon Deeprasertkul

Reputation: 195

Google map doesn't display when using ui-router

i tried to apply google map to my AngularJS project from this Link

and it works well without state (ui-router) but when i tried to put it into my project which has several states, map doesn't display but... it can search for a place and get longitude, latitude as you can see in the pic

enter image description here

Here's part of my code

Service: app.js

myApp.service('Map', function($q) {

    this.init = function() {
        var options = {
            center: new google.maps.LatLng(40.7127837, -74.00594130000002),
            zoom: 13,
            disableDefaultUI: true    
        }
        this.map = new google.maps.Map(
            document.getElementById("map"), options
        );
        this.places = new google.maps.places.PlacesService(this.map);
    }

    this.search = function(str) {
        var d = $q.defer();
        this.places.textSearch({query: str}, function(results, status) {
            if (status == 'OK') {
                d.resolve(results[0]);
            }
            else d.reject(status);
        });
        return d.promise;
    }

    this.addMarker = function(res) {
        if(this.marker) this.marker.setMap(null);
        this.marker = new google.maps.Marker({
            map: this.map,
            position: res.geometry.location,
            animation: google.maps.Animation.DROP
        });
        this.map.setCenter(res.geometry.location);
    }

});

Controller: app.js

myApp.controller('VenueController', function(Map,$rootScope, $scope, $auth, $state, $http) {

Map.init();

$scope.place = {};

$scope.search = function() {
    $scope.apiError = false;
    Map.search($scope.searchPlace)
    .then(
        function(res) { // success
            Map.addMarker(res);
            $scope.place.name = res.name;
            $scope.place.lat = res.geometry.location.lat();
            $scope.place.lng = res.geometry.location.lng();
        },
        function(status) { // error
            $scope.apiError = true;
            $scope.apiStatus = status;
        }
    );
}
});

HTML: venue.html

<div style="margin-top:20px;">
    <label> Location : </label>
    <form name="searchForm" novalidate ng-submit="search()">
    <div class="input-group">
        <input name="place" type="text" class="form-control" 
        ng-model="searchPlace" required autofocus />
        <span class="input-group-btn">
            <button class="btn btn-primary" 
            ng-disabled="searchForm.$invalid">Search</button>
        </span>
    </div>
</form>

<div id="map"></div>

<form name="resForm" class="form-horizontal" novalidate 
ng-submit="send()">
    <div class="form-group">
        <label for="resName" class="col-xs-2 control-label">Name</label>
        <div class="col-xs-10">
            <input name="resName" type="text" class="form-control" 
            ng-model="place.name" required />
        </div>
    </div>
    <div class="form-group">
        <label for="resLat" class="col-xs-2 control-label">Latitude</label>
        <div class="col-xs-10">
            <input name="resLat" type="number" class="form-control" 
            ng-model="place.lat" required />
        </div>
    </div>
    <div class="form-group">
        <label for="resLng" class="col-xs-2 control-label">Longitude</label>
        <div class="col-xs-10">
            <input name="resLng" type="number" class="form-control" 
            ng-model="place.lng" required />
        </div>
    </div>

Sorry if the code I show you is difficult to read

Please help, Thanks in advance

Upvotes: 1

Views: 533

Answers (1)

Matej P.
Matej P.

Reputation: 5383

When the div that contains map, or it's parent, or it's parent's parent (any DOM predecessor) has display:none style (what I presume happens when you change states: you hide some views and display other) the map view won't initialise properly. You have to trigger resize event on map when the visibility changes. (I think this is happening in your case, judging from the screenshot you provided, the API loaded sucesfuly, only the view is not properly initialised) Just add this code to the Map service:

this.resize = function() {
     if(this.map) google.maps.event.trigger(this.map, 'resize');
}

EDIT

In your code, the map is inside the div id="addVenue". So you need to trigger the resize right after the div is being displayed. To achieve this, add this function to your VenueController:

$scope.mapresize = function(){
    setTimeout(function(){ Map.resize(); }, 10);
}

And call it in the venue.html view when you are about to display the addVenue div. Find a line with link to href="#addVenue" and change it like this:

<div class="sm-st clearfix"  href="#addVenue" ng-click="mapresize()" data-toggle="tab">

ALSO!! there is another problem with your application. In style.css REMOVE these 3 lines:

img {
  max-width: 100% !important;
}

They cause google maps to not function properly. Because google maps uses images internally and if you add this constrain they will break.

Upvotes: 2

Related Questions