0

Edit: Invoking these two methods directly on the map object solved the issue:

leafletData.getMap().then(function(map)
{
    map.invalidateSize();
    map._onResize();
});

I have a little, yet pretty irritating issue with Leaflet directive for AngularJS (https://github.com/angular-ui/ui-leaflet) and Google Maps plugin (https://github.com/shramov/leaflet-plugins).

For some reason, sometimes markers load with no problems, yet no map is being shown. Refreshing the website helps but it isn't a solution...

Screenshots attached (taken on my phone but it happens on desktop browsers too):

image 1

Sometimes the map loads after a moment but with no bounds set:

image 2

How it should look like (and most of the time does):

image 3

View:

<div class="stations-map" ng-controller="mapCtrl" ng-show="mapObj.visible">
        <leaflet layers="mapObj.layers" lf-center="mapObj.center" bounds="mapObj.bounds" markers="mapObj.markers" height="480px" width="100%"></leaflet>
    </div>

Controller:

app.controller("mapCtrl", ['$scope', '$filter', 'propertyService', 'groupService', 'leafletBoundsHelpers', function ($scope, $filter, propertyService, groupService, leafletBoundsHelpers){
var properties = null;

var mapObj = {

    center: {},
    bounds: [],
    markers: {},

    layers: {

        baselayers:
        {
            googleRoadmap: {name: 'Google Streets', layerType: 'ROADMAP', type: 'google'}
        }

    },

    visible: false

};

var resetMap = function()
{
    mapObj.center = {};
    mapObj.bounds = [];
    mapObj.markers = {};
};

var resetMapAndHide = function()
{
    mapObj.center = {};
    mapObj.bounds = [];
    mapObj.markers = {};
    mapObj.visible = false;
};

var setMarkerMessage = function(res,item,property)
{
    var location = item.location.name;
    var value = null;
    var value_unit = null;

    if(res.data[item.id] == undefined)
    {
        return "<div id='popup-container'><div id='popup-value'>-</div><div id='popup-location'>" + location + "</div></div>";
    }
    else if(properties[item.property].name == 'PM')
    {
        value = $filter('number')(res.data[item.id].value['PM2.5'], 2);
        value_unit = " µg/m³";

        return "<div id='popup-container'><div id='popup-value'>" + value + value_unit + "</div><div id='popup-location'>" + location + "</div></div>";
    }
    else if(properties[item.property].name == 'pressure')
    {
        value = $filter('number')(res.data[item.id].value[property.name]/100, 2);
        value_unit = property.string_format.replace((/{(.*)}/.exec(property.string_format))[0],'');

        return "<div id='popup-container'><div id='popup-value'>" + value + value_unit + "</div><div id='popup-location'>" + location + "</div></div>";
    }

    value = $filter('number')(res.data[item.id].value[property.name], 2);
    value_unit = property.string_format.replace((/{(.*)}/.exec(property.string_format))[0],'');

    return "<div id='popup-container'><div id='popup-value'>" + value + value_unit + "</div><div id='popup-location'>" + location + "</div></div>";
};

var setNorthE = function(northE,item)
{
    if ( (northE.lat == null) || (northE.lat < item.location.latitude) )
    {
        northE.lat = item.location.latitude;
    }

    if ( (northE.lng == null) || (northE.lng < item.location.longitude) )
    {
        northE.lng = item.location.longitude;
    }
};

var setSouthW = function(southW,item)
{
    if ( (southW.lat == null) || (southW.lat > item.location.latitude) )
    {
        southW.lat = item.location.latitude;
    }

    if ( (southW.lng == null) || (southW.lng > item.location.longitude) )
    {
        southW.lng = item.location.longitude;
    }
};

$scope.mapObj = mapObj;

propertyService.getProperties().then(function(response)
{
    properties = response;
});

$scope.$on('group-chosen', function(event,id)
{
    var groupData = null;

    resetMap();

    groupService.getGroupById(id).then(function(response)
    {
        return response.data;

    }).then(function(response)
    {
        groupData = response;

        return groupService.getGroupSensorValues(id);

    }).then(function(response)
    {
        var groupProperty = properties[groupData.property.id];

        var northE =
        {
            lat: null,
            lng: null
        };

        var southW =
        {
            lat: null,
            lng: null
        };

        var i = 0;

        angular.forEach(groupData.sensors, function(item)
        {
            // add markers
            if ( (item.location.latitude !== null) && (item.location.longitude !== null) )
            {
                mapObj.markers['m'+i] = {};
                mapObj.markers['m'+i]['lat'] = item.location.latitude;
                mapObj.markers['m'+i]['lng'] = item.location.longitude;

                mapObj.markers['m'+i]['icon'] = {

                    type: 'div',
                    iconSize: [25,25],
                    className: 'divCircle'

                };

                mapObj.markers['m'+i]['getMessageScope'] = function()
                {
                    return $scope;
                };

                mapObj.markers['m'+i]['message'] = setMarkerMessage(response,item,groupProperty);
                mapObj.markers['m'+i]['compileMessage'] = true;

                mapObj.markers['m'+i]['popupOptions'] = {
                    closeButton: false
                };
            }

            setNorthE(northE,item);
            setSouthW(southW,item);

            i++;
        });

        var bounds = [];
        var northEast = [];
        var southWest = [];

        // temporary map's padding
        northEast.push(northE.lat+0.0001, northE.lng+0.0001);
        southWest.push(southW.lat-0.0001, southW.lng-0.0001);

        bounds.push(northEast,southWest);

        mapObj.bounds = leafletBoundsHelpers.createBoundsFromArray(bounds);
    });

    mapObj.visible = true;
    $scope.mapObj = mapObj;
});

$scope.$on('station-chosen', function()
{
    resetMapAndHide();
    $scope.mapObj = mapObj;
});

$scope.$on('data-switched', function()
{
    resetMapAndHide();
    $scope.mapObj = mapObj;
});}]);

Thanks in advance for any suggestions!

Jakub
  • 187
  • 1
  • 1
  • 9
  • I don't know this plugins, but I had simil problem with simple map google. The map need a $scope.apply or $timeout that allows a digest cycle and can render a map correctly – LorenzoBerti Aug 25 '16 at 07:26
  • Could you provide me with an example of usage in case of Google Maps? – Jakub Aug 25 '16 at 09:12

1 Answers1

1

I don't know this plugin but When I had a problem with google maps, I realized that was a problem of resize, so I have resolved my problem with trigger Resize event, maybe this example can help you

$scope.initializeMaps = function(test){
            if(test.gps){
                var arrLatLng = test.gps.split(',');
                var latlng = new google.maps.LatLng(arrLatLng[0], arrLatLng[1]);
            }else{
                var latlng = new google.maps.LatLng(37.42224,-122.0883822);
            }

            var myOptions = {
                zoom: 9,
                center: latlng,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            var map = new google.maps.Map(document.getElementById("map"),
                myOptions);

            var input = document.getElementById('maps-input');
            var searchBox = new google.maps.places.SearchBox(input);

            map.addListener('click', function (e) {
                placeMarker(e.latLng, map, test);
            });

            map.addListener('bounds_changed', function () {
                searchBox.setBounds(map.getBounds());

            });

            // THIS Is RESIZE EVENT THAT RENDER MAP
            $timeout(function(){
                google.maps.event.trigger(map, 'resize');
                if (marker && test.marker) {
                    map.setCenter(marker.getPosition());
                }
            },1);

        };
        //};
        var marker;

        function placeMarker(location, map, test) {
            $scope.$apply(function () {
                test.gps = location.lat() + "," + location.lng();

            });

            if (marker && test.marker) {
                marker.setPosition(location);

            } else {
                marker = new google.maps.Marker({
                    position: location,
                    map: map
                });
            }
            test.marker = true;
        };
LorenzoBerti
  • 6,704
  • 8
  • 47
  • 89
  • Thank you! Even though it wasn't exactly the issue in my case, it lead me to another solution and everything seems to be just fine: `leafletData.getMap().then(function(map)
{
 map.invalidateSize();
 map._onResize();
});` – Jakub Aug 25 '16 at 11:46