5

I am new in Angular and have a web app which displays a fullscreen google map. I want to add a "logout" button into the google map layout (not as header).

I know with javascript Google Maps Api, it is possible like :

var Logout = document.getElementById('Logout');
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(Logout);

But with the AGM - Angular Google Maps, I didn't find how.

Now I have that :

map.component.html

<button id="Logout" [(ngModel)]="logoutButton" class="toggle-button controls button" (click)="logout()">Logout</button>

<agm-map [latitude]="lat" [longitude]="lng" [zoom]=12 [mapTypeControl]="true" (boundsChange)="centerChanged($event)" (idle)="loadParkings()" >

    <agm-marker *ngFor="let park of parkings" [latitude]="park.location[0]" [longitude]="park.location[1]"></agm-marker>
</agm-map>

map.component.ts

import {GoogleMapsAPIWrapper} from '@agm/core';

declare var google: any;

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.css']
})

export class MapComponent implements OnInit {
  lat: number;
  lng: number;
  map: any;
  logoutButton: any;

  constructor(
    public mapApi: GoogleMapsAPIWrapper) {}

  ngOnInit(): void {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(position => {
        this.lat = position.coords.latitude;
        this.lng = position.coords.longitude;
      });
    } else {
      this.lat = 47.2275654;
      this.lng = -1.3849729;
    }
  }


  logout() {
    this.authenficationService.logout();
    this.router.navigate(['/login']);
  }
}
alliaces
  • 171
  • 1
  • 10

2 Answers2

12

I found my solution, few days ago and it looks like your answer. I used the event (mapReady) which gives an instance of the native map.

There is also how I manage to display a search box into the map.

map.component.html

<agm-map [latitude]="lat" [longitude]="lng" [zoom]=12 [mapTypeControl]="true" (boundsChange)="centerChanged($event)" (idle)="loadParkings()"
    (mapReady)="mapReady($event)" (boundsChange)="boundsChanged($event)">
    <button id="Settings" class="toggle-button controls button" [hidden]="hideSettings">
        <mat-icon aria-hidden="true">settings</mat-icon>
    </button>
    <button id="Profile" class="toogle-button controls button" (click)="profileClicked()">
        <mat-icon aria-hidden="true">account_circle</mat-icon>
    </button>
    <button id="Logout" class="toggle-button controls button" (click)="logout()">Logout</button>
    <input id="Map-Search" class="controls" type="text" placeholder="Search Box">
    <agm-marker *ngFor="let park of parkings" [latitude]="park.location[0]" [longitude]="park.location[1]"></agm-marker>
</agm-map>

map.component.ts

declare const google: any;

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.css'],
})

export class MapComponent {
    map: any;
    searchBox: any;

    [...]

    mapReady(event: any) {
        this.map = event;
        const input = document.getElementById('Map-Search');
        this.searchBox = new google.maps.places.SearchBox(input);
        this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(document.getElementById('Settings'));
        this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(document.getElementById('Profile'));
        this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
        this.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(document.getElementById('Logout'));

        this.searchBox.addListener('places_changed', () => this.goToSearchedPlace());
    }

    goToSearchedPlace() {
        const places = this.searchBox.getPlaces();
        if (places.length === 0) {
        return;
        }
        const bounds = new google.maps.LatLngBounds();
        places.forEach((place) => {
        if (place.geometry.viewport) {
            bounds.union(place.geometry.viewport);
        } else {
            bounds.extend(place.geometry.location);
        }
        });
        this.map.fitBounds(bounds);
    }
}
alliaces
  • 171
  • 1
  • 10
  • Thank You. works like a charm. I am wondering if there is a way to add an element to map when element is created dynamically, for example, using *ngIf? – Khasan 24-7 May 16 '18 at 06:46
  • 2
    As stated [here](https://developers.google.com/maps/documentation/javascript/examples/places-searchbox) inside the code sample in red, you probably need to import the 'places' library. Like so in your module: ```AgmCoreModule.forRoot({ libraries: ['places'] })```. This will add ```google.maps.places``` on the window object. – Brampage Jul 10 '19 at 12:53
  • I wonder, has something changed, as I don't have `.controls` on my AgmMap? – Ian Oct 15 '19 at 04:47
  • ok, so just removing the type of AgmMap still worked with a change in how i react to boundsChange – Ian Oct 15 '19 at 05:24
  • i have tried to add button on my agm map 'Set Location', but when i pitch or move map it getting flicker.. any help? – Ravi Mehta Oct 17 '19 at 08:30
  • Thanks, this gave me the idea how to add custom controls to a native typescript google maps library in my angular app, by using the same method - marking my element with an ID and adding it to my map controls with `doucument.getElementById()`. – Patronaut Dec 04 '20 at 08:34
0

I had the same problem a few days ago. I'm not sure if this is the correct way. You could get the map by getNativeMap() in GoogleMapsAPIWrapper. And then assign it to an any type variable, otherwise, it cannot find controls:

view-more-button.component.ts

import { Component, OnInit } from '@angular/core';
import { GoogleMapsAPIWrapper } from '@agm/core/services/google-maps-api-wrapper';
declare var google: any;

@Component({
  selector: 'app-view-more-button',
  templateUrl: './view-more-button.component.html',
  styleUrls: ['./view-more-button.component.css']
})
export class ViewMoreButtonComponent implements OnInit {

  private _isMoreMap: boolean;

  constructor(private _wrapper: GoogleMapsAPIWrapper) {
    this._isMoreMap = true;
  }

  ngOnInit() {
    this._wrapper.getNativeMap().then((m) => {
      // m type doesnt have controls declared. So need to store it to <any> first then use controls
      var nativeMap: any;
      nativeMap = m;
      nativeMap.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(document.getElementById("view-more-button"));
    });
  }

  private _click() {
    ...
  }

}

view-more-button.component.html

<button class="btn btn-primary" (click)="_click()" id="view-more-button">
  View More Map
</button>
Frank
  • 1,215
  • 12
  • 24