Angular, Google Maps autocomplete and geocoder

Voici  un module avec quelques  directives AngularJS  a utiliser avec Google Map V3 . Bien sur il existe un module complet mais aussi complexe avec AngularUI .Ici l avantage te la simplicité et la possibilité de modifier ce code a votre besoin.

La première directive est pour afficher la carte google : on peut lui passer plusieurs paramètres comme la liste des markers , le centre, les coordonnée géographique ...

<div ng-map style="height:400px;margin:12px;box-shadow:0 3px 25px black;"
        center="{ lat: 40, lon: -73 }"
        markers="[]"
 geo-coord="mapcoord"
 ></div>
La deuxième directive est le geoCoder qui consiste a chercher une adresse et l afficher sur la carte

<div class="input-append text-right"
             ng-geocoder
             ng-model="address"
             geo-coord="mapcoord">
</div>
La troisième directive est AddressAutocomplete  qui  procure une assistance a la saisie  des adresses et remplit un formulaire automatiquement .


<form class="form-horizontal" role="form">
   <div class="form-group">
   <label class="control-label col-sm-2 " for="email">Saisir adresse:</label>
   <div  class="col-sm-10">
 <input type="email" class="form-control" ng-model="fullAddress" 
    ng-address-autocomplete  
    street-name="streetName"
    city="city"
    zip-code="zipCode"
    country="country"
    street-number="streetNumber" />
   </div>
   </div>
    <br/> 
   <div class="form-group">
    <label class="control-label  " for="email">Numero:</label>
    <div>
    <input type="text" class="form-control" ng-model="streetNumber"/>
    </div>
    </div> 
    <br/>
    <div class="form-group">
     <label class="control-label  " for="email">Rue:</label>
     <div>
      <input type="text" class="form-control" ng-model="streetName"/>
     </div>
     </div> 
     <br/> 
     <div class="form-group">
     <label class="control-label  " for="email">Ville:</label>
     <div>
     <input type="text" class="form-control" ng-model="city"/>
     </div>
     </div> 
      <br/>
      <div class="form-group">
      <label class="control-label  " for="email">Code postal:</label>
      <div>
     <input type="text" class="form-control" ng-model="zipCode"/>
     </div>
     </div>
     <br/> 
     <div class="form-group">
       <label class="control-label  " for="email">Pays:</label>
     <div>
      <input type="text" class="form-control" ng-model="country"/>
    </div>
    </div> 
   </form>
Voici l exemple complet : Plunker
 <!DOCTYPE html>
<html   id='ng-app'  >
<head>
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css">

     
</head>

<body  ng-app="app" ng-controller="appCtrl">
 <h3 class="text-center">   Angular, Google Maps autocomplete and geocoder </h3>
<div class="text-center">
        <div class="input-append text-right" ng-geocoder ng-model="address" geo-coord="mapcoord">
        </div>
    </div>
     

    <!-- map -->
    <div ng-map style="height:400px;margin:12px;box-shadow:0 3px 25px black;"
        center="{ lat: 40, lon: -73 }"
        markers="[]"
  map="myMap"
  geo-coord="mapcoord"
    > 
    </div>
  <br/> <br/>
  
 <form class="form-horizontal" role="form">
  <div class="form-group">
  <label class="control-label col-sm-2 " for="email">Saisir adresse:</label>
  <div  class="col-sm-10">
   <input type="email" class="form-control" ng-model="fullAddress"  
         ng-address-autocomplete   
         street-name="streetName" 
         city="city"
         zip-code="zipCode"
         country="country"
         street-number="streetNumber" />
  </div>
  </div>
  <br/>  
  <div class="form-group">
  <label class="control-label  " for="email">Numero:</label>
  <div>
   <input type="text" class="form-control" ng-model="streetNumber"/> 
  </div>
  </div>  
  <br/>
  <div class="form-group">
  <label class="control-label  " for="email">Rue:</label>
  <div>
   <input type="text" class="form-control" ng-model="streetName"/> 
  </div>
  </div>  
  <br/> 
  <div class="form-group">
  <label class="control-label  " for="email">Ville:</label>
  <div>
   <input type="text" class="form-control" ng-model="city"/> 
  </div>
  </div>   
   <br/>
   <div class="form-group">
  <label class="control-label  " for="email">Code postal:</label>
  <div>
   <input type="text" class="form-control" ng-model="zipCode"/> 
  </div>
  </div>
  <br/>  
   <div class="form-group">
  <label class="control-label  " for="email">Pays:</label>
  <div>
   <input type="text" class="form-control" ng-model="country"/> 
  </div>
  </div> 
   </form>
  
     

     
</body>
<script src="http://maps.googleapis.com/maps/api/js?key=&sensor=false&extension=.js&libraries=places"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.16/angular.min.js"></script>

 <script>
 
 angular.module("ngMapModule", [])
  .directive("ngMap", function ($timeout) {
    return {
        restrict: "EA",
        replace: true,
        template: "<div></div>",
        scope: {
      geoCoord:"=",
            center: "=",        //{latitude: 10, longitude: 10 } .
            markers: "=",       //[{ lat: 10, lon: 10, name: "sName" }] .
            zoom: "@",          //(1  zoomed out, 25  zoomed in).
            mapTypeId: "@",     //(roadmap, satellite, hybrid, terrain).
            panControl: "@",    //show a pan control on the map.
            zoomControl: "@",   //show a zoom control on the map.
            scaleControl: "@"   //show scale control on the map.
        },
  controller:function($scope){
  $scope.updateMap=function(elem) {
                var options =getOptions();
                $scope.map = new google.maps.Map(elem, options);
                $scope.updateMarkers();
                google.maps.event.addListener($scope.map, 'center_changed', function () {
                    if ($scope.initCenter) clearTimeout($scope.initCenter);
                    $scope.initCenter = $timeout(function () {
                        if ($scope.center) {
                            if ($scope.map.center.lat() != $scope.center.lat ||
                                $scope.map.center.lng() != $scope.center.lon) {
                                $scope.center = { lat: $scope.map.center.lat(), lon: $scope.map.center.lng() };
                                if (!$scope.$$phase) $scope.$apply("center");
                            }
                        }
                    }, 500);
                });
            }
  $scope.updateMarkers=function() {
                if ($scope.map && $scope.markers) {
                    if ($scope.currentMarkers != null) {
                        for (var i = 0; i < $scope.currentMarkers.length; i++) {
                            $scope.currentMarkers[i] = m.setMap(null);
                        }
                    }
                    $scope.currentMarkers = [];
                    var markers = $scope.markers;
                    if (angular.isString(markers)) markers = $scope.$eval($scope.markers);
                    for (var i = 0; i < markers.length; i++) {
                        var m = markers[i];
                        var loc = new google.maps.LatLng(m.lat, m.lon);
                        var mm = new google.maps.Marker({ position: loc, map: $scope.map, title: m.name });
                        $scope.currentMarkers.push(mm);
                    }
                }
            }
  $scope.getLocation=function(loc) {
                if (loc == null) return new google.maps.LatLng(40, -73);
                if (angular.isString(loc)) loc = $scope.$eval(loc);
                return new google.maps.LatLng(loc.lat, loc.lon);
            }
  function getOptions() {
    var options =
       {
        center: new google.maps.LatLng(40, -73),
        zoom: 6,
        mapTypeId: "roadmap"
       };
    if ($scope.center) options.center = $scope.getLocation($scope.center);
    if ($scope.zoom) options.zoom = $scope.zoom / 1;
    if ($scope.mapTypeId) options.mapTypeId = $scope.mapTypeId;
    if ($scope.panControl) options.panControl = $scope.panControl;
    if ($scope.zoomControl) options.zoomControl = $scope.zoomControl;
    if ($scope.scaleControl) options.scaleControl = $scope.scaleControl;
    return options;
   }
  },
        link: function (scope, element, attrs) {
            var scopeArray = ["markers", "mapTypeId", "panControl", "zoomControl", "scaleControl"],toCenter  ;
            for (var i = 0, cnt = scopeArray.length; i < scopeArray.length; i++) {
                scope.$watch(scopeArray[i], function () {
                    cnt--;
                    if (cnt <= 0) {
                        scope.updateMap(element[0] );
                    }
                });
            }
            scope.$watch("zoom", function () {
                if (scope.map && scope.zoom)
                    scope.map.setZoom(scope.zoom / 1);
            });
            scope.$watch("center", function () {
                if (scope.map && scope.center)
                    scope.map.setCenter(scope.getLocation(scope.center));
            });
   scope.$watch("geoCoord", function (val) {
                if (val){
    var coord=new google.maps.LatLng(val.lat, val.lon);
    scope.map.setCenter(coord);
    scope.map.setZoom(12);
    }
                    
            });
   
        }
    };
}).directive("ngGeocoder", function () {
    return {
        restrict: "EA",
  template: '<input   type="text"  ng-model="ngModel" style="width:500px"/>'+
            '<button class="btn" type="button" ng-click="geoCode()" ng-disabled="address.length == 0" title="address" >'+
              '&nbsp;<i class="icon-search"></i></button>',
        scope: {
      ngModel:"=",
   geoCoord:"="
           },
  controller:function($scope){
       
   $scope.geoCode = function () {
    if ($scope.ngModel && $scope.ngModel.length > 0) {
     if (!$scope.geocoder) $scope.geocoder = new google.maps.Geocoder();
     $scope.geocoder.geocode({ 'address': $scope.ngModel }, function (results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
       var location = results[0].geometry.location;
       if (!$scope.$$phase) $scope.$apply(function(){
       $scope.geoCoord={ lat: location.lat(), lon: location.lng() }
       $scope.ngModel = results[0].formatted_address;
       });
       
        
      } else {
       alert("Sorry,  address produced no results.");
      }
     });
    }
   };
   
   
  },
  link: function (scope, element, attrs) {
  
  
  }
  }
 }).directive("ngAddressAutocomplete", function () {
    return {
        restrict: "EA",
        scope: {
      ngModel:"=",
      city:"=",
      zipCode:"=",
      country:"=",
   streetName:"=",
   streetNumber:"="
           },
  link: function (scope, element, attrs) {
   var autocomplete = new google.maps.places.Autocomplete(element[0]);
   google.maps.event.addListener(autocomplete, 'place_changed', function() {  
   var place = autocomplete.getPlace();  
    
   if (!scope.$$phase) scope.$apply(function(){
     var componenents=place.address_components||[];
     for(var i=0;i<componenents.length;i++){
      var item=componenents[i];
      if(item&&item.types){
         if(/route/gi.test(item.types[0])){
         scope.streetName =componenents[1].long_name;
         }
         if(/country/gi.test(item.types[0])){
         scope.country =item.long_name;
         }
         if(/street_number/gi.test(item.types[0])){
         scope.streetNumber =item.long_name;
         }
         if(/postal_code/gi.test(item.types[0])){
         scope.zipCode =item.long_name;
         }
         if(/dministrative_area_level_2|city/gi.test(item.types[0])){
         scope.city =item.long_name;
         }
        }
     }
   });
      
   })
  }
  }
 })
 var app = angular.module("app", ["ngMapModule"]);
     app.controller("appCtrl", function ($scope) {
  
  $scope.mapcoord
});
 </script>
</body>
Voir aussi sur Plunker

0 commentaires:

Enregistrer un commentaire