google_treetview

Angular 1.5 StreetView: directive vs component vs ES2015

A custom directive in Angular 1.5 in order to use the Google StreetView API.
Move the slider or click buttons to change location

Check out this Pen!

HTML

<div ng-app="myApp"
     ng-controller="AppCtrl as ctrl">
    
   <div class="controls">
     <button class="btn"
       ng-repeat="item in ctrl.cities"
       ng-click="ctrl.goto(item)">
       {{item.label}}
     </button>
   
     <input type="range" 
        min="0" max="360" 
        ng-model="ctrl.heading" />
   </div>

  <street-view 
    position="ctrl.location"
    heading="ctrl.heading"></street-view>
    
</div>

<script src="https://maps.googleapis.com/maps/api/js?key=[YOUR_KEY]" type="text/javascript"></script>
      
 

App Controller

angular.module('myApp', [])

.controller('AppCtrl', function() {
    // default location
    this.location = {
      lat: 37.869260,
      lng: -122.254811
    }
    
    // locations menu
    this.cities = [
      { label: 'NEW YORK', 
        lat: 40.758895, 
        lng: -73.985131
      },
      { label: 'LONDON', 
        lat: 51.5007998, 
        lng: -0.1199734 
      },
      { label: 'TOKYO', 
        lat: 35.647417, 
        lng: 139.7362426
      }
    ]
    
    // Change current location
    this.goto = function(city) {
      this.location = {
        lat: city.lat,
        lng: city.lng
      }
    }
})

< street-view /> directive

.directive('streetView', function() {
  return {
    restrict: 'E',
    scope: {
      position: '<',
      heading: '<',
    },
    template: '<div class="map"></div>',
    controller: function($scope, $element) {

      var el = $element.children()[0];
      var p = new google.maps.StreetViewPanorama(el);
      
      $scope.$watch('position', function(obj) {
        if (obj) {
          p.setPosition({
            lat: obj.lat,
            lng: obj.lng
         })
        }
      }.bind(this));
      
      $scope.$watch('heading', function(obj) {
        if (obj) {
          p.setPov(({
            heading: Number(obj),
            pitch: 0
          }))
        }
      }.bind(this));
    }
  };
}) 

CSS

body {
  padding: 20px;
}
.controls {
  width: 400px;
}

.map{
  width:100%;
  height: 250px; 
}


.component(…)

The same exact directive can be written as component:


.component('streetView', {
  bindings: {
    position: '<',
    heading: '<',
  },
  template: '<div class="map"></div>',
  controller: function($scope, $element) {
    var el = $element.children()[0];
    var p = new google.maps.StreetViewPanorama(el);

    $scope.$watch(
      function() { 
        return this.position;
      }.bind(this), 
      function(obj) {
        if (obj) {
          p.setPosition({
            lat: obj.lat,
            lng: obj.lng
          });
        }
      }.bind(this)
    );

    $scope.$watch(
      function() { 
        return this.heading; 
      }.bind(this), 
      function(obj) {
        if (obj) {
          p.setPov(({
            heading: Number(obj),
            pitch: 0
          }));
        }
    }.bind(this));
  }
}) 

Check out this Pen!

.component hooks and ES2015

Following the ES2015 version:

Component:

const streetView = {
   bindings: {
    position: '<',
    heading: '<',
  },
  template'<div class="map"></div>',
  controller: StreetViewController,
}

Controller:

class StreetViewController {
   constructor($scope, $element) {
     this.el = $element.children()[0];
     this.scope = $scope;
   }

   $onInit() {
     const s = this.scope;
     const p = new  google.maps.StreetViewPanorama(this.el);
     
     s.$watch(
      () => this.position, 
      (obj = {}) => {
        p.setPosition({
          lat: obj.lat,
          lng: obj.lng,
        });
     });
     
     s.$watch(
      () => this.heading, 
      (obj = 180) => {
        p.setPov(({
          heading: Number(obj),
          pitch: 0
        }));
     });
   }
}

NOTE: $onInit represents a Lifecycle hook (Angular 1.5.x) and is automatically invoked after the component has been initialized and all its bindings have been set up. Although I have used it into the previous ES2015 script, hooks are available in ES5 too ; )

App Controller

The main application controller can be now written as an ES2015 class too:

class appController {

  constructor() {
    // default location
    this.location = {
      lat: 37.869260,
      lng: -122.254811,
    }
    
    // locations menu
    this.cities = [
      { label: 'NEW YORK', 
        lat: 40.758895, 
        lng: -73.985131
      },
      { label: 'LONDON', 
        lat: 51.5007998, 
        lng: -0.1199734 
      },
      { label: 'TOKYO', 
        lat: 35.647417, 
        lng: 139.7362426
      }
    ];
  }
  
  // Change current location
  goto(city) {
    const { lat, lng } = city;
    this.location = { lat, lng };
  }
}

angular.module('myApp', [])
  .component('streetView', streetView)
  .controller('MapCtrl', appController)
Check out this Pen!

Leave a Reply

Your email address will not be published. Required fields are marked *

Published on: 2 June 2016
Posted by:
Discussion: Leave a comment