4

I have been trying to use mapbox.js geo map within angularjs.

Map: http://bl.ocks.org/wboykinm/c77e7c891bfc52157843#index.html

JSON data: http://bl.ocks.org/wboykinm/raw/c77e7c891bfc52157843/42d7ab5d1a432a88e905bf14705424ac40ba4480/saplaces.geojson

When i try to use that code within angularjs, nothing is seen on the page. Just empty.

<!DOCTYPE html>
<html lang="en-us">
<head>
<title>Learn and Understand AngularJS</title>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta charset="UTF-8">
<!-- load Jquery Style -->

<link rel="stylesheet" href="//code.jquery.com/ui/1.11.3/themes/smoothness/jquery-ui.css">

<!-- load bootstrap and fontawesome via CDN -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />

<link href='https://api.tiles.mapbox.com/mapbox.js/v1.6.3/mapbox.css' rel='stylesheet' />
<link href='//api.tiles.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/MarkerCluster.css' rel='stylesheet' />
<link href='//api.tiles.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/MarkerCluster.Default.css' rel='stylesheet' />

 <style>
    body {
        padding: 0;
        margin: 0;
    }
    html, body, #map {
        height: 100%;
    }
</style>


<!-- load jQuery, d3 and angular via CDN -->
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="https://api.tiles.mapbox.com/mapbox.js/v1.6.3/mapbox.js">   </script>
 <script src='//api.tiles.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/leaflet.markercluster.js'>
</script>
<script src="//code.angularjs.org/1.3.0-rc.1/angular.min.js"></script>
<script src="//code.angularjs.org/1.3.0-rc.1/angular-route.min.js"></script>
<script src="//code.angularjs.org/1.3.0-rc.1/angular-resource.min.js"> </script>


</head>

<body ng-app="myApp">

   <header id="wrapper">
    <nav class="navbar navbar-default" style="background: #FBFAFF;">
        <div class="container">
            <div class="navbar-header">
                <a class="navbar-brand" href="/">
                     <p style="margin:0;padding:0;font-weight:bold;font- size:1.05em;">Geo Map Using Mapbox</p>
                </a>
            </div>

            <ul class="nav navbar-nav navbar-right small" style="font-weight:bold;font-size:1em;">
                <li><a href="#/geomap"><i></i> Geo Map</a>
                </li>
            </ul>
        </div>
    </nav>
</header>


<h2> This is main page </h2>    

<div ng-view>
</div>


<script>
    var myApp = angular.module('myApp', ['ngRoute', 'ngResource']);


    myApp.config(function ($routeProvider) {
        $routeProvider
            .when('/geomap', {
                templateUrl: 'pages/geomap.html',
                controller: 'firstController'
            })

    });


    myApp.controller('firstController', ['$rootScope', '$scope', '$log', '$location', '$timeout', '$http',
        function ($rootScope, $scope, $log, $location, $timeout, $http) {                

            var baseLayer =    L.tileLayer('http://a.tiles.mapbox.com/v3/landplanner.map-4y9ngu48/{z}/{x}/{y}.png', {
                maxZoom: 18
            });

            // DEFINE THE CLUSTER LAYER
            var markers = L.markerClusterGroup();

            $http.get('json/mapjson.json')
                .success(function (data) {                        
                    console.log(data)
                    var geojson = L.geoJson(data, {
                        onEachFeature: function (feature, layer) {
                            // USE A CUSTOM MARKER
                            layer.setIcon(L.mapbox.marker.icon({
                                'marker-symbol': 'circle-stroked',
                                'marker-color': '59245f'
                            }));
                        }
                    });
                    markers.addLayer(geojson);

                    // CONSTRUCT THE MAP
                    var map = L.map('map', {
                        maxZoom: 9
                    }).fitBounds(markers.getBounds());

                    baseLayer.addTo(map);
                    markers.addTo(map);
                })
 }])
</script>
</body>
</html>

geomap.html file:

<div id="map">
</div>
<p> In the map page </p>

I am not able to fix it. Can anyone please provide some idea where i am doing wrong. I have also attached the snap of my webpage.

Note: Also another small issue. When i tried $http.get to directly the url 'http://bl.ocks.org/wboykinm/raw/c77e7c891bfc52157843/42d7ab5d1a432a88e905bf14705424ac40ba4480/saplaces.geojson', i am getting Cross origin error. So i have downloaded the json into a local file and using it. Any idea how to avoid this.

enter image description here

user3057556
  • 141
  • 2
  • 9
  • On the mapbox website: https://www.mapbox.com/help/mapbox-with-angular/, they recommend the following angular directive: https://github.com/tombatossals/angular-leaflet-directive – mg1075 Jan 10 '16 at 04:59

1 Answers1

5

The problem you're experiencing is that at the moment you're creating a new instance of L.mapbox.map, your template isn't available yet. So the instance can find the element it needs to build the map. Solution is to create a directive which creates your map instance and passes it back to a callback function in your controller so that you can use it:

Stylesheet:

body {
    margin: 0;
}

body, html, .leaflet-container {
    height: 100%;
}

Template:

<mapbox callback="callback"></mapbox>

Directive:

angular.module('app').directive('mapbox', [
    function () {
        return {
            restrict: 'EA',
            replace: true,
            scope: {
                callback: "="
            },
            template: '<div></div>',
            link: function (scope, element, attributes) {
                L.mapbox.accessToken = 'pk.eyJ1IjoicGF1bC12ZXJob2V2ZW4iLCJhIjoiZ1BtMWhPSSJ9.wQGnLyl1DiuIQuS0U_PtiQ';
                var map = L.mapbox.map(element[0], 'examples.map-i86nkdio');
                scope.callback(map);
            }
        };
    }
]);

Controller:

angular.module('app').controller('rootController', [
    '$scope',
    function ($scope) {
        // Gets called when the directive is ready:
        $scope.callback = function (map) {
            // Map is available here to use:
            map.setView([51.433333, 5.483333], 12);
        };
    }
]);

Here's a working example on Plunker: http://plnkr.co/edit/p7aWsLofWZZtADXLcWxd?p=preview (You're not supposed to use the example mapid and user token, you've got to replace those with your own)

The other problem CORS problem you're having isn't solvable, not as long as you don't control the server you are downloading the file from. If you we're controlling the server you could set the access-control-allow-origin header to accept your request. But since you're not controlling the server, you can't. Just download the files to your own server. A work around is to use a proxy which adds the right headers but you got to keep in mind that it's not done to run on other peoples bandwidth if you don't have permission. They could block you or worse. If they wanted people to run files straight off their server they would have made it so that you could.

Here's some more information on CORS: http://en.wikipedia.org/wiki/Cross-origin_resource_sharing

iH8
  • 27,722
  • 4
  • 67
  • 76