From 629f574bf93626fa373ffb0981ac34872d2473ca Mon Sep 17 00:00:00 2001 From: Matthew Ehrlich Date: Fri, 30 Aug 2019 09:57:49 -0700 Subject: [PATCH 1/9] feat(google-maps): Add google-map-marker component Add a google-map-marker component that when used as a child to a google-map component, will display a marker on the map. --- packages.bzl | 1 + src/dev-app/system-config.js | 1 + src/google-maps/google-map-marker/BUILD.bazel | 50 ++++ .../google-map-marker-module.ts | 16 ++ .../google-map-marker/google-map-marker.md | 0 .../google-map-marker.spec.ts | 1 + .../google-map-marker/google-map-marker.ts | 231 ++++++++++++++++++ src/google-maps/google-map-marker/index.ts | 9 + .../google-map-marker/public-api.ts | 10 + .../google-map-marker/tsconfig-build.json | 15 ++ src/google-maps/google-map/BUILD.bazel | 1 + src/google-maps/google-map/google-map.ts | 21 +- src/google-maps/public-api.ts | 1 + 13 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 src/google-maps/google-map-marker/BUILD.bazel create mode 100644 src/google-maps/google-map-marker/google-map-marker-module.ts create mode 100644 src/google-maps/google-map-marker/google-map-marker.md create mode 100644 src/google-maps/google-map-marker/google-map-marker.spec.ts create mode 100644 src/google-maps/google-map-marker/google-map-marker.ts create mode 100644 src/google-maps/google-map-marker/index.ts create mode 100644 src/google-maps/google-map-marker/public-api.ts create mode 100644 src/google-maps/google-map-marker/tsconfig-build.json diff --git a/packages.bzl b/packages.bzl index f0cf5c7d29c7..54d7ce0cf41d 100644 --- a/packages.bzl +++ b/packages.bzl @@ -82,6 +82,7 @@ MATERIAL_SCSS_LIBS = [ GOOGLE_MAPS_PACKAGES = [ "google-map", + "google-map-marker", ] GOOGLE_MAPS_TARGETS = ["//src/google-maps"] + ["//src/google-maps/%s" % p for p in GOOGLE_MAPS_PACKAGES] diff --git a/src/dev-app/system-config.js b/src/dev-app/system-config.js index ea418484e985..d792ce80fee1 100644 --- a/src/dev-app/system-config.js +++ b/src/dev-app/system-config.js @@ -57,6 +57,7 @@ var MATERIAL_PACKAGES = [ var GOOGLE_MAPS_PACKAGES = [ 'google-map', + 'google-map-marker', ]; var MATERIAL_EXPERIMENTAL_PACKAGES = [ diff --git a/src/google-maps/google-map-marker/BUILD.bazel b/src/google-maps/google-map-marker/BUILD.bazel new file mode 100644 index 000000000000..2db2c3fdc2e0 --- /dev/null +++ b/src/google-maps/google-map-marker/BUILD.bazel @@ -0,0 +1,50 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "//tools:defaults.bzl", + "markdown_to_html", + "ng_module", + "ng_test_library", + "ng_web_test_suite", +) + +ng_module( + name = "google-map-marker", + srcs = glob( + ["**/*.ts"], + exclude = ["**/*.spec.ts"], + ), + module_name = "@angular/google-maps/google-map-marker", + deps = [ + "@npm//@angular/core", + "@npm//@types/googlemaps", + "@npm//rxjs", + ], +) + +ng_test_library( + name = "unit_test_sources", + srcs = glob( + ["**/*.spec.ts"], + exclude = ["**/*.e2e.spec.ts"], + ), + deps = [ + ":google-map-marker", + "@npm//@angular/platform-browser", + ], +) + +ng_web_test_suite( + name = "unit_tests", + deps = [":unit_test_sources"], +) + +markdown_to_html( + name = "overview", + srcs = [":google-map-marker.md"], +) + +filegroup( + name = "source-files", + srcs = glob(["**/*.ts"]), +) diff --git a/src/google-maps/google-map-marker/google-map-marker-module.ts b/src/google-maps/google-map-marker/google-map-marker-module.ts new file mode 100644 index 000000000000..c16a396e3ac8 --- /dev/null +++ b/src/google-maps/google-map-marker/google-map-marker-module.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { NgModule } from '@angular/core'; +import { GoogleMapMarker } from './google-map-marker'; + +@NgModule({ + exports: [GoogleMapMarker], + declarations: [GoogleMapMarker], +}) +export class GoogleMapMarkerModule { } diff --git a/src/google-maps/google-map-marker/google-map-marker.md b/src/google-maps/google-map-marker/google-map-marker.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/google-maps/google-map-marker/google-map-marker.spec.ts b/src/google-maps/google-map-marker/google-map-marker.spec.ts new file mode 100644 index 000000000000..4190b7bfcfd1 --- /dev/null +++ b/src/google-maps/google-map-marker/google-map-marker.spec.ts @@ -0,0 +1 @@ +descript('GoogleMapMarker', () => {}); diff --git a/src/google-maps/google-map-marker/google-map-marker.ts b/src/google-maps/google-map-marker/google-map-marker.ts new file mode 100644 index 000000000000..e2f9028eeb44 --- /dev/null +++ b/src/google-maps/google-map-marker/google-map-marker.ts @@ -0,0 +1,231 @@ +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core'; +import {BehaviorSubject, combineLatest, Observable, ReplaySubject, Subject} from 'rxjs'; +import {map, takeUntil} from 'rxjs/operators'; + +export const DEFAULT_OPTIONS = { + position: { lat: 37.421995, lng: -122.084092 }, +}; + +/** + * Angular component that renders a Google Maps marker via the Google Maps JavaScript API. + * @see https://developers.google.com/maps/documentation/javascript/reference/marker + */ +@Component({ + selector: 'google-map-marker', + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class GoogleMapMarker implements OnInit, OnDestroy { + @Input() set options(options: google.maps.MarkerOptions) { + this._options.next(options || DEFAULT_OPTIONS); + } + + @Input() set title(title: string) { + this._title.next(title); + } + + @Input() set position(position: google.maps.LatLngLiteral) { + this._position.next(position); + } + + @Input() set label(label: string|google.maps.MarkerLabel) { + this._label.next(label); + } + + @Input() set clickable(clickable: boolean) { + this._clickable.next(clickable); + } + + /** */ + @Output() animationChanged = new EventEmitter(); + + /** */ + @Output() mapClick = new EventEmitter(); + + /** */ + @Output() clickableChanged = new EventEmitter(); + + /** */ + @Output() cursorChanged = new EventEmitter(); + + /** */ + @Output() mapDblclick = new EventEmitter(); + + /** */ + @Output() mapDrag = new EventEmitter(); + + /** */ + @Output() mapDragend = new EventEmitter(); + + /** */ + @Output() draggableChanged = new EventEmitter(); + + /** */ + @Output() mapDragstart = new EventEmitter(); + + /** */ + @Output() flatChanged = new EventEmitter(); + + /** */ + @Output() iconChanged = new EventEmitter(); + + /** */ + @Output() mapMousedown = new EventEmitter(); + + /** */ + @Output() mapMouseout = new EventEmitter(); + + /** */ + @Output() mapMouseover = new EventEmitter(); + + /** */ + @Output() mapMouseup = new EventEmitter(); + + /** */ + @Output() positionChanged = new EventEmitter(); + + /** */ + @Output() mapRightclick = new EventEmitter(); + + /** */ + @Output() shapeChanged = new EventEmitter(); + + /** */ + @Output() titleChanged = new EventEmitter(); + + /** */ + @Output() visibleChanged = new EventEmitter(); + + /** */ + @Output() zindexChanged = new EventEmitter(); + + private readonly _options = new BehaviorSubject(DEFAULT_OPTIONS); + private readonly _title = new BehaviorSubject(undefined); + private readonly _position = new BehaviorSubject(undefined); + private readonly _label = new BehaviorSubject(undefined); + private readonly _clickable = new BehaviorSubject(true); + + private readonly _map = new ReplaySubject(1); + + private readonly _destroy = new Subject(); + + private readonly _listeners: google.maps.MapsEventListener[] = []; + + private _marker?: google.maps.Marker; + private _hasMap = false; + + ngOnInit() { + const combinedOptionsChanges = this._combineOptions(); + + combineLatest(this._map, combinedOptionsChanges).pipe(takeUntil(this._destroy)).subscribe(([map, options]) => { + if (this._marker) { + this._marker.setOptions(options); + } else { + this._marker = new google.maps.Marker(options); + this._marker.setMap(map); + this._initializeEventHandlers(); + } + }); + } + + ngOnDestroy() { + this._destroy.next(); + this._destroy.complete(); + for (let listener of this._listeners) { + listener.remove(); + } + if (this._marker) { + this._marker.setMap(null); + } + } + + setMap(map: google.maps.Map) { + if (!this._hasMap) { + this._map.next(map); + this._hasMap = true; + } + } + + getAnimation(): google.maps.Animation|null { + return this._marker!.getAnimation() || null; + } + + getClickable(): boolean { + return this._marker!.getClickable(); + } + + getCursor(): string|null { + return this._marker!.getCursor() || null; + } + + getDraggable(): boolean { + return !!this._marker!.getDraggable(); + } + + getIcon(): string|google.maps.Icon|google.maps.Symbol|null { + return this._marker!.getIcon() || null; + } + + getLabel(): google.maps.MarkerLabel|null { + return this._marker!.getLabel() || null; + } + + getOpacity(): number|null { + return this._marker!.getOpacity() || null; + } + + getPosition(): google.maps.LatLng|null { + return this._marker!.getPosition() || null; + } + + getShape(): google.maps.MarkerShape|null { + return this._marker!.getShape() || null; + } + + getTitle(): string|null { + return this._marker!.getTitle() || null; + } + + getVisible(): boolean { + return this._marker!.getVisible(); + } + + getZIndex(): number|null { + return this._marker!.getZIndex() || null; + } + + private _combineOptions(): Observable { + return combineLatest(this._options, this._title, this._position, this._label, this._clickable, this._map) + .pipe(map(([options, title, position, label, clickable, map]) => { + const combinedOptions: google.maps.MarkerOptions = { + ...options, + title: title || options.title, + position: position || options.position, + label: label || options.label, + clickable: clickable || options.clickable, + map: map || null, + }; + return combinedOptions; + })); + } + + private _initializeEventHandlers() { + const eventHandlers = new Map>([]); + const mouseEventHandlers = new Map>([]); + + eventHandlers.forEach((eventHandler: EventEmitter, name: string) => { + if (eventHandler.observers.length > 0) { + this._listeners.push(this._marker!.addListener(name, () => { + eventHandler.emit(); + })); + } + }); + mouseEventHandlers.forEach((eventHandler: EventEmitter, name: string) => { + if (eventHandler.observers.length > 0) { + this._listeners.push(this._marker!.addListener(name, (event: google.maps.MouseEvent) => { + eventHandler.emit(event); + })); + } + }); + } +} diff --git a/src/google-maps/google-map-marker/index.ts b/src/google-maps/google-map-marker/index.ts new file mode 100644 index 000000000000..676ca90f1ffa --- /dev/null +++ b/src/google-maps/google-map-marker/index.ts @@ -0,0 +1,9 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export * from './public-api'; diff --git a/src/google-maps/google-map-marker/public-api.ts b/src/google-maps/google-map-marker/public-api.ts new file mode 100644 index 000000000000..a4062d292728 --- /dev/null +++ b/src/google-maps/google-map-marker/public-api.ts @@ -0,0 +1,10 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export * from './google-map-marker-module'; +export * from './google-map-marker'; diff --git a/src/google-maps/google-map-marker/tsconfig-build.json b/src/google-maps/google-map-marker/tsconfig-build.json new file mode 100644 index 000000000000..3eccc179e82c --- /dev/null +++ b/src/google-maps/google-map-marker/tsconfig-build.json @@ -0,0 +1,15 @@ +{ + "extends": "../tsconfig-build", + "files": [ + "public-api.ts", + "../typings.d.ts" + ], + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "strictMetadataEmit": true, + "flatModuleOutFile": "index.js", + "flatModuleId": "@angular/google-maps/google-map-marker", + "skipTemplateCodegen": true, + "fullTemplateTypeCheck": true + } +} diff --git a/src/google-maps/google-map/BUILD.bazel b/src/google-maps/google-map/BUILD.bazel index 29bfa1e34ca7..dc01ce0a987d 100644 --- a/src/google-maps/google-map/BUILD.bazel +++ b/src/google-maps/google-map/BUILD.bazel @@ -19,6 +19,7 @@ ng_module( "@npm//@angular/core", "@npm//@types/googlemaps", "@npm//rxjs", + "//src/google-maps/google-map-marker", ], ) diff --git a/src/google-maps/google-map/google-map.ts b/src/google-maps/google-map/google-map.ts index 6c26042c215a..6aaccefd2e01 100644 --- a/src/google-maps/google-map/google-map.ts +++ b/src/google-maps/google-map/google-map.ts @@ -1,6 +1,7 @@ import { ChangeDetectionStrategy, Component, + ContentChildren, ElementRef, EventEmitter, Input, @@ -8,9 +9,11 @@ import { OnDestroy, OnInit, Output, + QueryList, } from '@angular/core'; -import {BehaviorSubject, combineLatest, Observable, Subject} from 'rxjs'; import {map, shareReplay, take, takeUntil} from 'rxjs/operators'; +import {BehaviorSubject, combineLatest, Observable, ReplaySubject, Subject} from 'rxjs'; +import {GoogleMapMarker} from '@angular/google-maps/google-map-marker'; interface GoogleMapsWindow extends Window { google?: typeof google; @@ -172,6 +175,10 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy { */ @Output() zoomChanged = new EventEmitter(); + @ContentChildren(GoogleMapMarker) set markers(markers: QueryList) { + this._markers.next(markers.toArray()); + } + private _mapEl: HTMLElement; private _googleMap!: UpdatedGoogleMap; @@ -181,6 +188,8 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy { private readonly _center = new BehaviorSubject(undefined); private readonly _zoom = new BehaviorSubject(undefined); + private readonly _markers = new ReplaySubject(1); + private readonly _destroy = new Subject(); constructor(private readonly _elementRef: ElementRef) { @@ -211,6 +220,8 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy { }); this._watchForOptionsChanges(googleMapChanges, combinedOptionsChanges); + + this._watchForMarkerChanges(googleMapChanges); } ngOnDestroy() { @@ -445,4 +456,12 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy { })); } } + + private _watchForMarkerChanges(googleMapChanges: Observable) { + combineLatest(googleMapChanges, this._markers).pipe(takeUntil(this._destroy)).subscribe(([googleMap, markers]) => { + for (let marker of markers) { + marker.setMap(googleMap); + } + }); + } } diff --git a/src/google-maps/public-api.ts b/src/google-maps/public-api.ts index 9d11682064d7..a1a6a64c2279 100644 --- a/src/google-maps/public-api.ts +++ b/src/google-maps/public-api.ts @@ -7,3 +7,4 @@ */ export * from '@angular/google-maps/google-map'; +export * from '@angular/google-maps/google-map-marker'; From 0fd04cae55fdeda50a2ec79edb785191291d1d8a Mon Sep 17 00:00:00 2001 From: Matthew Ehrlich Date: Fri, 30 Aug 2019 13:56:09 -0700 Subject: [PATCH 2/9] feat(google-maps): Add google-map-marker component Add tests for the google-map-marker component. --- .../google-map/google-map-demo-module.ts | 2 + src/dev-app/google-map/google-map-demo.html | 6 +- src/dev-app/google-map/google-map-demo.ts | 7 + src/google-maps/google-map-marker/BUILD.bazel | 1 + .../google-map-marker.spec.ts | 70 ++++++- .../google-map-marker/google-map-marker.ts | 180 +++++++++++++++--- src/google-maps/google-map/BUILD.bazel | 2 +- src/google-maps/google-map/google-map.spec.ts | 6 +- src/google-maps/google-map/google-map.ts | 2 +- .../{google-map => }/testing/BUILD.bazel | 0 .../testing/fake-google-map-utils.ts | 24 ++- 11 files changed, 271 insertions(+), 29 deletions(-) rename src/google-maps/{google-map => }/testing/BUILD.bazel (100%) rename src/google-maps/{google-map => }/testing/fake-google-map-utils.ts (54%) diff --git a/src/dev-app/google-map/google-map-demo-module.ts b/src/dev-app/google-map/google-map-demo-module.ts index 5473fb36884c..6a3bea0644d1 100644 --- a/src/dev-app/google-map/google-map-demo-module.ts +++ b/src/dev-app/google-map/google-map-demo-module.ts @@ -10,6 +10,7 @@ import {CommonModule} from '@angular/common'; import {HttpClientJsonpModule, HttpClientModule} from '@angular/common/http'; import {NgModule} from '@angular/core'; import {GoogleMapModule} from '@angular/google-maps/google-map'; +import {GoogleMapMarkerModule} from '@angular/google-maps/google-map-marker'; import {RouterModule} from '@angular/router'; import {GoogleMapDemo} from './google-map-demo'; @@ -18,6 +19,7 @@ import {GoogleMapDemo} from './google-map-demo'; imports: [ CommonModule, GoogleMapModule, + GoogleMapMarkerModule, HttpClientJsonpModule, HttpClientModule, RouterModule.forChild([{path: '', component: GoogleMapDemo}]), diff --git a/src/dev-app/google-map/google-map-demo.html b/src/dev-app/google-map/google-map-demo.html index 64fe1d08b0e1..cbc5fe26b7ef 100644 --- a/src/dev-app/google-map/google-map-demo.html +++ b/src/dev-app/google-map/google-map-demo.html @@ -4,7 +4,11 @@ [center]="center" [zoom]="zoom" (mapClick)="handleClick($event)" - (mapMousemove)="handleMove($event)"> + (mapMousemove)="handleMove($event)"> + +
Latitude: {{display?.lat}}
Longitude: {{display?.lng}}
diff --git a/src/dev-app/google-map/google-map-demo.ts b/src/dev-app/google-map/google-map-demo.ts index 0f3d7f7a8492..431eabb22170 100644 --- a/src/dev-app/google-map/google-map-demo.ts +++ b/src/dev-app/google-map/google-map-demo.ts @@ -19,6 +19,8 @@ export class GoogleMapDemo { isReady = false; center = {lat: 24, lng: 12}; + markerOptions = {draggable: false}; + gettysburg = {lat: 39.830205, lng:-77.232949}; zoom = 4; display?: google.maps.LatLngLiteral; @@ -36,4 +38,9 @@ export class GoogleMapDemo { handleMove(event: google.maps.MouseEvent) { this.display = event.latLng.toJSON(); } + + clickMarker(event: google.maps.MouseEvent) { + console.log(this.markerOptions); + this.markerOptions = {draggable: true}; + } } diff --git a/src/google-maps/google-map-marker/BUILD.bazel b/src/google-maps/google-map-marker/BUILD.bazel index 2db2c3fdc2e0..1f6614bbf8a9 100644 --- a/src/google-maps/google-map-marker/BUILD.bazel +++ b/src/google-maps/google-map-marker/BUILD.bazel @@ -30,6 +30,7 @@ ng_test_library( ), deps = [ ":google-map-marker", + "//src/google-maps/testing", "@npm//@angular/platform-browser", ], ) diff --git a/src/google-maps/google-map-marker/google-map-marker.spec.ts b/src/google-maps/google-map-marker/google-map-marker.spec.ts index 4190b7bfcfd1..dfec6fe08d3c 100644 --- a/src/google-maps/google-map-marker/google-map-marker.spec.ts +++ b/src/google-maps/google-map-marker/google-map-marker.spec.ts @@ -1 +1,69 @@ -descript('GoogleMapMarker', () => {}); +import { Component } from '@angular/core'; +import { async, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; + +import {DEFAULT_OPTIONS, GoogleMapMarkerModule} from './index'; + +import {createMarkerSpy, createMarkerConstructorSpy, TestingWindow} from '../testing/fake-google-map-utils'; + +describe('GoogleMapMarker', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [GoogleMapMarkerModule], + declarations: [TestApp], + }); + })); + + beforeEach(() => { + TestBed.compileComponents(); + }); + + afterEach(() => { + const testingWindow: TestingWindow = window; + delete testingWindow.google; + }); + + it('initializes a Google Map marker', () => { + let markerSpy = createMarkerSpy(DEFAULT_OPTIONS); + let markerConstructorSpy = createMarkerConstructorSpy(markerSpy); + + const fixture = TestBed.createComponent(TestApp); + fixture.detectChanges(); + + expect(markerConstructorSpy).toHaveBeenCalledWith(DEFAULT_OPTIONS); + }); + + it('sets marker inputs', () => {}); + + it('sets marker options, ignoring map', () => {}); + + it('gives precedence to specific inputs over options', () => {}); + + it('sets the map on the marker only once', () => {}); + + it('exposes methods that provide information about the marker', () => {}); + + it('initializes marker event handlers', () => {}); +}); + +@Component({ + selector: 'test-app', + template: ``, +}) +class TestApp { + title?: string; + position?: google.maps.LatLngLiteral; + label?: string; + clickable?: boolean; + options?: google.maps.MarkerOptions; + + handleClick() {} + + handlePositionChanged() {} +} diff --git a/src/google-maps/google-map-marker/google-map-marker.ts b/src/google-maps/google-map-marker/google-map-marker.ts index e2f9028eeb44..9b1108a27341 100644 --- a/src/google-maps/google-map-marker/google-map-marker.ts +++ b/src/google-maps/google-map-marker/google-map-marker.ts @@ -36,67 +36,130 @@ export class GoogleMapMarker implements OnInit, OnDestroy { this._clickable.next(clickable); } - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.animation_changed + */ @Output() animationChanged = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.click + */ @Output() mapClick = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.clickable_changed + */ @Output() clickableChanged = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.cursor_changed + */ @Output() cursorChanged = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.dblclick + */ @Output() mapDblclick = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.drag + */ @Output() mapDrag = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.dragend + */ @Output() mapDragend = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.draggable_changed + */ @Output() draggableChanged = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.dragstart + */ @Output() mapDragstart = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.flat_changed + */ @Output() flatChanged = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.icon_changed + */ @Output() iconChanged = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.mousedown + */ @Output() mapMousedown = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.mouseout + */ @Output() mapMouseout = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.mouseover + */ @Output() mapMouseover = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.mouseup + */ @Output() mapMouseup = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.position_changed + */ @Output() positionChanged = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.rightclick + */ @Output() mapRightclick = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.shape_changed + */ @Output() shapeChanged = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.title_changed + */ @Output() titleChanged = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.visible_changed + */ @Output() visibleChanged = new EventEmitter(); - /** */ + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.zindex_changed + */ @Output() zindexChanged = new EventEmitter(); private readonly _options = new BehaviorSubject(DEFAULT_OPTIONS); @@ -146,50 +209,98 @@ export class GoogleMapMarker implements OnInit, OnDestroy { } } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getAnimation + */ getAnimation(): google.maps.Animation|null { return this._marker!.getAnimation() || null; } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getClickable + */ getClickable(): boolean { return this._marker!.getClickable(); } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getCursor + */ getCursor(): string|null { return this._marker!.getCursor() || null; } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getDraggable + */ getDraggable(): boolean { return !!this._marker!.getDraggable(); } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getIcon + */ getIcon(): string|google.maps.Icon|google.maps.Symbol|null { return this._marker!.getIcon() || null; } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getLabel + */ getLabel(): google.maps.MarkerLabel|null { return this._marker!.getLabel() || null; } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getOpacity + */ getOpacity(): number|null { return this._marker!.getOpacity() || null; } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getPosition + */ getPosition(): google.maps.LatLng|null { return this._marker!.getPosition() || null; } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getShape + */ getShape(): google.maps.MarkerShape|null { return this._marker!.getShape() || null; } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getTitle + */ getTitle(): string|null { return this._marker!.getTitle() || null; } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getVisible + */ getVisible(): boolean { return this._marker!.getVisible(); } + /** + * See + * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getZIndex + */ getZIndex(): number|null { return this._marker!.getZIndex() || null; } @@ -210,8 +321,31 @@ export class GoogleMapMarker implements OnInit, OnDestroy { } private _initializeEventHandlers() { - const eventHandlers = new Map>([]); - const mouseEventHandlers = new Map>([]); + const eventHandlers = new Map>([ + ['animation_changed', this.animationChanged], + ['clickable_changed', this.clickableChanged], + ['cursor_changed', this.cursorChanged], + ['draggable_changed', this.draggableChanged], + ['flat_changed', this.flatChanged], + ['icon_changed', this.iconChanged], + ['position_changed', this.positionChanged], + ['shape_changed', this.shapeChanged], + ['title_changed', this.titleChanged], + ['visible_changed', this.visibleChanged], + ['zindex_changed', this.zindexChanged], + ]); + const mouseEventHandlers = new Map>([ + ['click', this.mapClick], + ['dblclick', this.mapDblclick], + ['drag', this.mapDrag], + ['dragend', this.mapDragend], + ['dragstart', this.mapDragstart], + ['mousedown', this.mapMousedown], + ['mouseout', this.mapMouseout], + ['mouseover', this.mapMouseover], + ['mouseup', this.mapMouseup], + ['rightclick', this.mapRightclick], + ]); eventHandlers.forEach((eventHandler: EventEmitter, name: string) => { if (eventHandler.observers.length > 0) { diff --git a/src/google-maps/google-map/BUILD.bazel b/src/google-maps/google-map/BUILD.bazel index dc01ce0a987d..5f5a5cdf8f1e 100644 --- a/src/google-maps/google-map/BUILD.bazel +++ b/src/google-maps/google-map/BUILD.bazel @@ -31,7 +31,7 @@ ng_test_library( ), deps = [ ":google-map", - "//src/google-maps/google-map/testing", + "//src/google-maps/testing", "@npm//@angular/platform-browser", ], ) diff --git a/src/google-maps/google-map/google-map.spec.ts b/src/google-maps/google-map/google-map.spec.ts index 2b5590b1ce27..9738c87a79cb 100644 --- a/src/google-maps/google-map/google-map.spec.ts +++ b/src/google-maps/google-map/google-map.spec.ts @@ -14,7 +14,7 @@ import { createMapConstructorSpy, createMapSpy, TestingWindow -} from './testing/fake-google-map-utils'; +} from '../testing/fake-google-map-utils'; /** Represents boundaries of a map to be used in tests. */ const testBounds: google.maps.LatLngBoundsLiteral = { @@ -237,6 +237,10 @@ describe('GoogleMap', () => { expect(mapSpy.addListener).not.toHaveBeenCalledWith('tilt_changed', jasmine.any(Function)); expect(mapSpy.addListener).not.toHaveBeenCalledWith('zoom_changed', jasmine.any(Function)); }); + + it('calls setMap on all child marker components', () => { + + }); }); @Component({ diff --git a/src/google-maps/google-map/google-map.ts b/src/google-maps/google-map/google-map.ts index 6aaccefd2e01..6aafe62ef7d1 100644 --- a/src/google-maps/google-map/google-map.ts +++ b/src/google-maps/google-map/google-map.ts @@ -47,7 +47,7 @@ export const DEFAULT_WIDTH = '500px'; @Component({ selector: 'google-map', changeDetection: ChangeDetectionStrategy.OnPush, - template: '
', + template: '
', }) export class GoogleMap implements OnChanges, OnInit, OnDestroy { @Input() height = DEFAULT_HEIGHT; diff --git a/src/google-maps/google-map/testing/BUILD.bazel b/src/google-maps/testing/BUILD.bazel similarity index 100% rename from src/google-maps/google-map/testing/BUILD.bazel rename to src/google-maps/testing/BUILD.bazel diff --git a/src/google-maps/google-map/testing/fake-google-map-utils.ts b/src/google-maps/testing/fake-google-map-utils.ts similarity index 54% rename from src/google-maps/google-map/testing/fake-google-map-utils.ts rename to src/google-maps/testing/fake-google-map-utils.ts index ec25af092404..fb6ce0d812cd 100644 --- a/src/google-maps/google-map/testing/fake-google-map-utils.ts +++ b/src/google-maps/testing/fake-google-map-utils.ts @@ -1,10 +1,11 @@ -import {UpdatedGoogleMap} from '../index'; +import {UpdatedGoogleMap} from '../google-map/index'; /** Window interface for testing */ export interface TestingWindow extends Window { google?: { maps: { Map: jasmine.Spy; + Marker: jasmine.Spy; }; }; } @@ -37,3 +38,24 @@ export function createMapConstructorSpy( } return mapConstructorSpy; } + +/** Creates a jasmine.SpyObj for a google.maps.Marker */ +export function createMarkerSpy(options: google.maps.MarkerOptions): jasmine.SpyObj { + const markerSpy = jasmine.createSpyObj('google.maps.Marker', ['setMap', 'addListener', 'getAnimation', 'getClickable', 'getCursor', +'getDraggable', 'getIcon', 'getLabel', 'getOpacity', 'getPosition', 'getShape', 'getTitle', 'getVisible', +'getZIndex']); +markerSpy.addListener.and.returnValue({remove: () => {}}); +} + +/** Creates a jasmine.Spy to watch for the constructor of a google.maps.Marker */ +export function createMarkerConstructorSpy(markerSpy: jasmine.SpyObj): jasmine.Spy { + const markerConstructorSpy = jasmine.createSpy('Marker constructor', (_options: google.maps.MarkerOptions) => { + return markerSpy; + }); + testingWindow.google = { + maps: { + 'Marker': markerConstructorSpy, + }, + }; + return markerConstructorSpy; +} From acb121bf098054e19ac6fab8c0ff6e91e3b5d3a1 Mon Sep 17 00:00:00 2001 From: Matthew Ehrlich Date: Tue, 3 Sep 2019 11:34:03 -0700 Subject: [PATCH 3/9] feat(google-maps) Add google-map-marker component Add tests to Google Map marker component. --- src/dev-app/google-map/google-map-demo.html | 2 +- src/dev-app/google-map/google-map-demo.ts | 2 +- .../google-map-marker-module.ts | 4 +- .../google-map-marker.spec.ts | 224 ++++++++++++++++-- .../google-map-marker/google-map-marker.ts | 161 +++++++------ src/google-maps/google-map/BUILD.bazel | 3 +- src/google-maps/google-map/google-map.spec.ts | 36 ++- src/google-maps/google-map/google-map.ts | 12 +- .../testing/fake-google-map-utils.ts | 33 ++- 9 files changed, 357 insertions(+), 120 deletions(-) diff --git a/src/dev-app/google-map/google-map-demo.html b/src/dev-app/google-map/google-map-demo.html index cbc5fe26b7ef..c55e49239272 100644 --- a/src/dev-app/google-map/google-map-demo.html +++ b/src/dev-app/google-map/google-map-demo.html @@ -5,7 +5,7 @@ [zoom]="zoom" (mapClick)="handleClick($event)" (mapMousemove)="handleMove($event)"> - diff --git a/src/dev-app/google-map/google-map-demo.ts b/src/dev-app/google-map/google-map-demo.ts index 431eabb22170..9f454e9ea5cf 100644 --- a/src/dev-app/google-map/google-map-demo.ts +++ b/src/dev-app/google-map/google-map-demo.ts @@ -20,7 +20,7 @@ export class GoogleMapDemo { center = {lat: 24, lng: 12}; markerOptions = {draggable: false}; - gettysburg = {lat: 39.830205, lng:-77.232949}; + markerPosition = {lat: 39.830205, lng: -77.232949}; zoom = 4; display?: google.maps.LatLngLiteral; diff --git a/src/google-maps/google-map-marker/google-map-marker-module.ts b/src/google-maps/google-map-marker/google-map-marker-module.ts index c16a396e3ac8..4805c379e713 100644 --- a/src/google-maps/google-map-marker/google-map-marker-module.ts +++ b/src/google-maps/google-map-marker/google-map-marker-module.ts @@ -6,8 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import { NgModule } from '@angular/core'; -import { GoogleMapMarker } from './google-map-marker'; +import {NgModule} from '@angular/core'; +import {GoogleMapMarker} from './google-map-marker'; @NgModule({ exports: [GoogleMapMarker], diff --git a/src/google-maps/google-map-marker/google-map-marker.spec.ts b/src/google-maps/google-map-marker/google-map-marker.spec.ts index dfec6fe08d3c..6a3de80ad9b7 100644 --- a/src/google-maps/google-map-marker/google-map-marker.spec.ts +++ b/src/google-maps/google-map-marker/google-map-marker.spec.ts @@ -1,10 +1,14 @@ -import { Component } from '@angular/core'; -import { async, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; +import {Component} from '@angular/core'; +import {async, TestBed} from '@angular/core/testing'; +import {By} from '@angular/platform-browser'; -import {DEFAULT_OPTIONS, GoogleMapMarkerModule} from './index'; +import { + createMarkerConstructorSpy, + createMarkerSpy, + TestingWindow +} from '../testing/fake-google-map-utils'; -import {createMarkerSpy, createMarkerConstructorSpy, TestingWindow} from '../testing/fake-google-map-utils'; +import {DEFAULT_MARKER_OPTIONS, GoogleMapMarker, GoogleMapMarkerModule} from './index'; describe('GoogleMapMarker', () => { beforeEach(async(() => { @@ -24,26 +28,214 @@ describe('GoogleMapMarker', () => { }); it('initializes a Google Map marker', () => { - let markerSpy = createMarkerSpy(DEFAULT_OPTIONS); - let markerConstructorSpy = createMarkerConstructorSpy(markerSpy); + let markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); + let markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); const fixture = TestBed.createComponent(TestApp); + const fakeMap = {} as unknown as google.maps.Map; + const markerComponent = + fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; + markerComponent.setMap(fakeMap); fixture.detectChanges(); - expect(markerConstructorSpy).toHaveBeenCalledWith(DEFAULT_OPTIONS); + expect(markerConstructorSpy).toHaveBeenCalledWith({ + ...DEFAULT_MARKER_OPTIONS, + title: undefined, + label: undefined, + clickable: undefined, + map: fakeMap + }); + }); + + it('sets marker inputs', () => { + const fakeMap = {} as unknown as google.maps.Map; + const options: google.maps.MarkerOptions = { + position: {lat: 3, lng: 5}, + title: 'marker title', + label: 'marker label', + clickable: false, + map: fakeMap, + }; + let markerSpy = createMarkerSpy(options); + let markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); + + const fixture = TestBed.createComponent(TestApp); + fixture.componentInstance.position = options.position; + fixture.componentInstance.title = options.title; + fixture.componentInstance.label = options.label; + fixture.componentInstance.clickable = options.clickable; + const markerComponent = + fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; + markerComponent.setMap(fakeMap); + fixture.detectChanges(); + + expect(markerConstructorSpy).toHaveBeenCalledWith(options); + }); + + it('sets marker options, ignoring map', () => { + const fakeMap = {} as unknown as google.maps.Map; + const options: google.maps.MarkerOptions = { + position: {lat: 3, lng: 5}, + title: 'marker title', + label: 'marker label', + clickable: false, + icon: 'icon name', + }; + let markerSpy = createMarkerSpy(options); + let markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); + + const fixture = TestBed.createComponent(TestApp); + fixture.componentInstance.options = options; + const markerComponent = + fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; + markerComponent.setMap(fakeMap); + fixture.detectChanges(); + + expect(markerConstructorSpy).toHaveBeenCalledWith({...options, map: fakeMap}); }); - it('sets marker inputs', () => {}); + it('gives precedence to specific inputs over options', () => { + const fakeMap = {} as unknown as google.maps.Map; + const options: google.maps.MarkerOptions = { + position: {lat: 3, lng: 5}, + title: 'marker title', + label: 'marker label', + clickable: false, + icon: 'icon name', + }; + const expectedOptions: google.maps.MarkerOptions = { + position: {lat: 5, lng: 12}, + title: 'updated title', + label: 'updated label', + clickable: true, + icon: 'icon name', + map: fakeMap, + }; + let markerSpy = createMarkerSpy(options); + let markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); + + const fixture = TestBed.createComponent(TestApp); + fixture.componentInstance.position = expectedOptions.position; + fixture.componentInstance.title = expectedOptions.title; + fixture.componentInstance.label = expectedOptions.label; + fixture.componentInstance.clickable = expectedOptions.clickable; + fixture.componentInstance.options = options; + const markerComponent = + fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; + markerComponent.setMap(fakeMap); + fixture.detectChanges(); - it('sets marker options, ignoring map', () => {}); + expect(markerConstructorSpy).toHaveBeenCalledWith(expectedOptions); + }); - it('gives precedence to specific inputs over options', () => {}); + it('sets the map on the marker only once', () => { + let markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); + let markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); - it('sets the map on the marker only once', () => {}); + const fixture = TestBed.createComponent(TestApp); + const fakeMap = {} as unknown as google.maps.Map; + const fakeMap2 = {testValue: 'test'} as unknown as google.maps.Map; + const markerComponent = + fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; + markerComponent.setMap(fakeMap); + markerComponent.setMap(fakeMap2); + fixture.detectChanges(); + + expect(markerConstructorSpy).toHaveBeenCalledWith({ + ...DEFAULT_MARKER_OPTIONS, + title: undefined, + label: undefined, + clickable: undefined, + map: fakeMap + }); + expect(markerSpy.setOptions).not.toHaveBeenCalled(); + }); - it('exposes methods that provide information about the marker', () => {}); + it('exposes methods that provide information about the marker', () => { + let markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); + createMarkerConstructorSpy(markerSpy).and.callThrough(); - it('initializes marker event handlers', () => {}); + const fixture = TestBed.createComponent(TestApp); + const fakeMap = {} as unknown as google.maps.Map; + const markerComponent = + fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; + markerComponent.setMap(fakeMap); + fixture.detectChanges(); + + markerSpy.getAnimation.and.returnValue(null); + expect(markerComponent.getAnimation()).toBe(null); + + markerSpy.getClickable.and.returnValue(true); + expect(markerComponent.getClickable()).toBe(true); + + markerSpy.getCursor.and.returnValue('cursor'); + expect(markerComponent.getCursor()).toBe('cursor'); + + markerSpy.getDraggable.and.returnValue(true); + expect(markerComponent.getDraggable()).toBe(true); + + markerSpy.getIcon.and.returnValue('icon'); + expect(markerComponent.getIcon()).toBe('icon'); + + markerSpy.getLabel.and.returnValue('label'); + expect(markerComponent.getLabel()).toBe('label'); + + markerSpy.getOpacity.and.returnValue(5); + expect(markerComponent.getOpacity()).toBe(5); + + markerSpy.getPosition.and.returnValue({lat: 1, lng: 2}); + expect(markerComponent.getPosition()).toEqual({lat: 1, lng: 2}); + + markerSpy.getShape.and.returnValue(null); + expect(markerComponent.getShape()).toBe(null); + + markerSpy.getTitle.and.returnValue('title'); + expect(markerComponent.getTitle()).toBe('title'); + + markerSpy.getVisible.and.returnValue(true); + expect(markerComponent.getVisible()).toBe(true); + + markerSpy.getZIndex.and.returnValue(2); + expect(markerComponent.getZIndex()).toBe(2); + }); + + it('initializes marker event handlers', () => { + let markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); + createMarkerConstructorSpy(markerSpy).and.callThrough(); + + const fixture = TestBed.createComponent(TestApp); + const fakeMap = {} as unknown as google.maps.Map; + const markerComponent = + fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; + markerComponent.setMap(fakeMap); + fixture.detectChanges(); + + expect(markerSpy.addListener) + .not.toHaveBeenCalledWith('animation_changed', jasmine.any(Function)); + expect(markerSpy.addListener).toHaveBeenCalledWith('click', jasmine.any(Function)); + expect(markerSpy.addListener) + .not.toHaveBeenCalledWith('clickable_changed', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('cursor_changed', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('dblclick', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('drag', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('dragend', jasmine.any(Function)); + expect(markerSpy.addListener) + .not.toHaveBeenCalledWith('draggable_changed', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('dragstart', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('flat_changed', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('icon_changed', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('mousedown', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('mouseout', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('mouseover', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('mouseup', jasmine.any(Function)); + expect(markerSpy.addListener).toHaveBeenCalledWith('position_changed', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('rightclick', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('shape_changed', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('title_changed', jasmine.any(Function)); + expect(markerSpy.addListener) + .not.toHaveBeenCalledWith('visible_changed', jasmine.any(Function)); + expect(markerSpy.addListener).not.toHaveBeenCalledWith('zindex_changed', jasmine.any(Function)); + }); }); @Component({ @@ -58,8 +250,8 @@ describe('GoogleMapMarker', () => { }) class TestApp { title?: string; - position?: google.maps.LatLngLiteral; - label?: string; + position?: google.maps.LatLng|google.maps.LatLngLiteral; + label?: string|google.maps.MarkerLabel; clickable?: boolean; options?: google.maps.MarkerOptions; diff --git a/src/google-maps/google-map-marker/google-map-marker.ts b/src/google-maps/google-map-marker/google-map-marker.ts index 9b1108a27341..3adde5b687ec 100644 --- a/src/google-maps/google-map-marker/google-map-marker.ts +++ b/src/google-maps/google-map-marker/google-map-marker.ts @@ -1,14 +1,26 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + OnDestroy, + OnInit, + Output +} from '@angular/core'; import {BehaviorSubject, combineLatest, Observable, ReplaySubject, Subject} from 'rxjs'; import {map, takeUntil} from 'rxjs/operators'; -export const DEFAULT_OPTIONS = { - position: { lat: 37.421995, lng: -122.084092 }, +/** + * Default options for the Google Maps marker component. Displays a marker + * at the Googleplex. + */ +export const DEFAULT_MARKER_OPTIONS = { + position: {lat: 37.421995, lng: -122.084092}, }; /** * Angular component that renders a Google Maps marker via the Google Maps JavaScript API. - * @see https://developers.google.com/maps/documentation/javascript/reference/marker + * @see developers.google.com/maps/documentation/javascript/reference/marker */ @Component({ selector: 'google-map-marker', @@ -17,7 +29,7 @@ export const DEFAULT_OPTIONS = { }) export class GoogleMapMarker implements OnInit, OnDestroy { @Input() set options(options: google.maps.MarkerOptions) { - this._options.next(options || DEFAULT_OPTIONS); + this._options.next(options || DEFAULT_MARKER_OPTIONS); } @Input() set title(title: string) { @@ -38,135 +50,137 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.animation_changed + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.animation_changed */ @Output() animationChanged = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.click + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.click */ @Output() mapClick = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.clickable_changed + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.clickable_changed */ @Output() clickableChanged = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.cursor_changed + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.cursor_changed */ @Output() cursorChanged = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.dblclick + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.dblclick */ @Output() mapDblclick = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.drag + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.drag */ @Output() mapDrag = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.dragend + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.dragend */ @Output() mapDragend = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.draggable_changed + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.draggable_changed */ @Output() draggableChanged = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.dragstart + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.dragstart */ @Output() mapDragstart = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.flat_changed + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.flat_changed */ @Output() flatChanged = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.icon_changed + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.icon_changed */ @Output() iconChanged = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.mousedown + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.mousedown */ @Output() mapMousedown = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.mouseout + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.mouseout */ @Output() mapMouseout = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.mouseover + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.mouseover */ @Output() mapMouseover = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.mouseup + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.mouseup */ @Output() mapMouseup = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.position_changed + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.position_changed */ @Output() positionChanged = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.rightclick + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.rightclick */ @Output() mapRightclick = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.shape_changed + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.shape_changed */ @Output() shapeChanged = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.title_changed + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.title_changed */ @Output() titleChanged = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.visible_changed + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.visible_changed */ @Output() visibleChanged = new EventEmitter(); /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.zindex_changed + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.zindex_changed */ @Output() zindexChanged = new EventEmitter(); - private readonly _options = new BehaviorSubject(DEFAULT_OPTIONS); + private readonly _options = + new BehaviorSubject(DEFAULT_MARKER_OPTIONS); private readonly _title = new BehaviorSubject(undefined); private readonly _position = new BehaviorSubject(undefined); - private readonly _label = new BehaviorSubject(undefined); - private readonly _clickable = new BehaviorSubject(true); + private readonly _label = + new BehaviorSubject(undefined); + private readonly _clickable = new BehaviorSubject(undefined); private readonly _map = new ReplaySubject(1); @@ -180,15 +194,17 @@ export class GoogleMapMarker implements OnInit, OnDestroy { ngOnInit() { const combinedOptionsChanges = this._combineOptions(); - combineLatest(this._map, combinedOptionsChanges).pipe(takeUntil(this._destroy)).subscribe(([map, options]) => { - if (this._marker) { - this._marker.setOptions(options); - } else { - this._marker = new google.maps.Marker(options); - this._marker.setMap(map); - this._initializeEventHandlers(); - } - }); + combineLatest(this._map, combinedOptionsChanges) + .pipe(takeUntil(this._destroy)) + .subscribe(([googleMap, options]) => { + if (this._marker) { + this._marker.setOptions(options); + } else { + this._marker = new google.maps.Marker(options); + this._marker.setMap(googleMap); + this._initializeEventHandlers(); + } + }); } ngOnDestroy() { @@ -202,16 +218,16 @@ export class GoogleMapMarker implements OnInit, OnDestroy { } } - setMap(map: google.maps.Map) { + setMap(googleMap: google.maps.Map) { if (!this._hasMap) { - this._map.next(map); + this._map.next(googleMap); this._hasMap = true; } } /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getAnimation + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getAnimation */ getAnimation(): google.maps.Animation|null { return this._marker!.getAnimation() || null; @@ -219,7 +235,7 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getClickable + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getClickable */ getClickable(): boolean { return this._marker!.getClickable(); @@ -227,7 +243,7 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getCursor + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getCursor */ getCursor(): string|null { return this._marker!.getCursor() || null; @@ -235,7 +251,7 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getDraggable + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getDraggable */ getDraggable(): boolean { return !!this._marker!.getDraggable(); @@ -243,7 +259,7 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getIcon + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getIcon */ getIcon(): string|google.maps.Icon|google.maps.Symbol|null { return this._marker!.getIcon() || null; @@ -251,7 +267,7 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getLabel + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getLabel */ getLabel(): google.maps.MarkerLabel|null { return this._marker!.getLabel() || null; @@ -259,7 +275,7 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getOpacity + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getOpacity */ getOpacity(): number|null { return this._marker!.getOpacity() || null; @@ -267,7 +283,7 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getPosition + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getPosition */ getPosition(): google.maps.LatLng|null { return this._marker!.getPosition() || null; @@ -275,7 +291,7 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getShape + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getShape */ getShape(): google.maps.MarkerShape|null { return this._marker!.getShape() || null; @@ -283,7 +299,7 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getTitle + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getTitle */ getTitle(): string|null { return this._marker!.getTitle() || null; @@ -291,7 +307,7 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getVisible + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getVisible */ getVisible(): boolean { return this._marker!.getVisible(); @@ -299,25 +315,26 @@ export class GoogleMapMarker implements OnInit, OnDestroy { /** * See - * https://developers.google.com/maps/documentation/javascript/reference/marker#Marker.getZIndex + * developers.google.com/maps/documentation/javascript/reference/marker#Marker.getZIndex */ getZIndex(): number|null { return this._marker!.getZIndex() || null; } private _combineOptions(): Observable { - return combineLatest(this._options, this._title, this._position, this._label, this._clickable, this._map) - .pipe(map(([options, title, position, label, clickable, map]) => { - const combinedOptions: google.maps.MarkerOptions = { - ...options, - title: title || options.title, - position: position || options.position, - label: label || options.label, - clickable: clickable || options.clickable, - map: map || null, - }; - return combinedOptions; - })); + return combineLatest( + this._options, this._title, this._position, this._label, this._clickable, this._map) + .pipe(map(([options, title, position, label, clickable, googleMap]) => { + const combinedOptions: google.maps.MarkerOptions = { + ...options, + title: title || options.title, + position: position || options.position, + label: label || options.label, + clickable: clickable !== undefined ? clickable : options.clickable, + map: googleMap || null, + }; + return combinedOptions; + })); } private _initializeEventHandlers() { @@ -354,12 +371,14 @@ export class GoogleMapMarker implements OnInit, OnDestroy { })); } }); - mouseEventHandlers.forEach((eventHandler: EventEmitter, name: string) => { - if (eventHandler.observers.length > 0) { - this._listeners.push(this._marker!.addListener(name, (event: google.maps.MouseEvent) => { - eventHandler.emit(event); - })); - } - }); + mouseEventHandlers.forEach( + (eventHandler: EventEmitter, name: string) => { + if (eventHandler.observers.length > 0) { + this._listeners.push( + this._marker!.addListener(name, (event: google.maps.MouseEvent) => { + eventHandler.emit(event); + })); + } + }); } } diff --git a/src/google-maps/google-map/BUILD.bazel b/src/google-maps/google-map/BUILD.bazel index 5f5a5cdf8f1e..ed141523cfc3 100644 --- a/src/google-maps/google-map/BUILD.bazel +++ b/src/google-maps/google-map/BUILD.bazel @@ -16,10 +16,10 @@ ng_module( ), module_name = "@angular/google-maps/google-map", deps = [ + "//src/google-maps/google-map-marker", "@npm//@angular/core", "@npm//@types/googlemaps", "@npm//rxjs", - "//src/google-maps/google-map-marker", ], ) @@ -31,6 +31,7 @@ ng_test_library( ), deps = [ ":google-map", + "//src/google-maps/google-map-marker", "//src/google-maps/testing", "@npm//@angular/platform-browser", ], diff --git a/src/google-maps/google-map/google-map.spec.ts b/src/google-maps/google-map/google-map.spec.ts index 9738c87a79cb..1c1fcfa6ca58 100644 --- a/src/google-maps/google-map/google-map.spec.ts +++ b/src/google-maps/google-map/google-map.spec.ts @@ -2,6 +2,13 @@ import {Component} from '@angular/core'; import {async, TestBed} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; +import {GoogleMapMarker, GoogleMapMarkerModule} from '../google-map-marker/index'; +import { + createMapConstructorSpy, + createMapSpy, + TestingWindow +} from '../testing/fake-google-map-utils'; + import { DEFAULT_HEIGHT, DEFAULT_OPTIONS, @@ -10,11 +17,6 @@ import { GoogleMapModule, UpdatedGoogleMap } from './index'; -import { - createMapConstructorSpy, - createMapSpy, - TestingWindow -} from '../testing/fake-google-map-utils'; /** Represents boundaries of a map to be used in tests. */ const testBounds: google.maps.LatLngBoundsLiteral = { @@ -36,7 +38,10 @@ describe('GoogleMap', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [GoogleMapModule], + imports: [ + GoogleMapModule, + GoogleMapMarkerModule, + ], declarations: [TestApp], }); })); @@ -238,8 +243,17 @@ describe('GoogleMap', () => { expect(mapSpy.addListener).not.toHaveBeenCalledWith('zoom_changed', jasmine.any(Function)); }); - it('calls setMap on all child marker components', () => { + it('calls setMap on child marker components', () => { + mapSpy = createMapSpy(DEFAULT_OPTIONS); + createMapConstructorSpy(mapSpy).and.callThrough(); + + const fixture = TestBed.createComponent(TestApp); + const markerComponent = + fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; + spyOn(markerComponent, 'setMap').and.callThrough(); + fixture.detectChanges(); + expect(markerComponent.setMap).toHaveBeenCalledWith(mapSpy); }); }); @@ -250,9 +264,11 @@ describe('GoogleMap', () => { [center]="center" [zoom]="zoom" [options]="options" - (mapClick)="handleClick" - (centerChanged)="handleCenterChanged" - (mapRightclick)="handleRightclick">`, + (mapClick)="handleClick($event)" + (centerChanged)="handleCenterChanged()" + (mapRightclick)="handleRightclick($event)"> + + `, }) class TestApp { height?: string; diff --git a/src/google-maps/google-map/google-map.ts b/src/google-maps/google-map/google-map.ts index 6aafe62ef7d1..867e08386eff 100644 --- a/src/google-maps/google-map/google-map.ts +++ b/src/google-maps/google-map/google-map.ts @@ -458,10 +458,12 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy { } private _watchForMarkerChanges(googleMapChanges: Observable) { - combineLatest(googleMapChanges, this._markers).pipe(takeUntil(this._destroy)).subscribe(([googleMap, markers]) => { - for (let marker of markers) { - marker.setMap(googleMap); - } - }); + combineLatest(googleMapChanges, this._markers) + .pipe(takeUntil(this._destroy)) + .subscribe(([googleMap, markers]) => { + for (let marker of markers) { + marker.setMap(googleMap); + } + }); } } diff --git a/src/google-maps/testing/fake-google-map-utils.ts b/src/google-maps/testing/fake-google-map-utils.ts index fb6ce0d812cd..6d09a5fe3239 100644 --- a/src/google-maps/testing/fake-google-map-utils.ts +++ b/src/google-maps/testing/fake-google-map-utils.ts @@ -4,8 +4,8 @@ import {UpdatedGoogleMap} from '../google-map/index'; export interface TestingWindow extends Window { google?: { maps: { - Map: jasmine.Spy; - Marker: jasmine.Spy; + Map?: jasmine.Spy; + Marker?: jasmine.Spy; }; }; } @@ -13,8 +13,8 @@ export interface TestingWindow extends Window { /** Creates a jasmine.SpyObj for a google.maps.Map. */ export function createMapSpy(options: google.maps.MapOptions): jasmine.SpyObj { const mapSpy = jasmine.createSpyObj('google.maps.Map', [ - 'setOptions', 'addListener', 'fitBounds', 'panBy', 'panTo', 'panToBounds', 'getBounds', - 'getCenter', 'getClickableIcons', 'getHeading', 'getMapTypeId', 'getProjection', + 'setOptions', 'setMap', 'addListener', 'fitBounds', 'panBy', 'panTo', 'panToBounds', + 'getBounds', 'getCenter', 'getClickableIcons', 'getHeading', 'getMapTypeId', 'getProjection', 'getStreetView', 'getTilt', 'getZoom' ]); mapSpy.addListener.and.returnValue({remove: () => {}}); @@ -40,18 +40,25 @@ export function createMapConstructorSpy( } /** Creates a jasmine.SpyObj for a google.maps.Marker */ -export function createMarkerSpy(options: google.maps.MarkerOptions): jasmine.SpyObj { - const markerSpy = jasmine.createSpyObj('google.maps.Marker', ['setMap', 'addListener', 'getAnimation', 'getClickable', 'getCursor', -'getDraggable', 'getIcon', 'getLabel', 'getOpacity', 'getPosition', 'getShape', 'getTitle', 'getVisible', -'getZIndex']); -markerSpy.addListener.and.returnValue({remove: () => {}}); +export function createMarkerSpy(options: google.maps.MarkerOptions): + jasmine.SpyObj { + const markerSpy = jasmine.createSpyObj('google.maps.Marker', [ + 'setOptions', 'setMap', 'addListener', 'getAnimation', 'getClickable', 'getCursor', + 'getDraggable', 'getIcon', 'getLabel', 'getOpacity', 'getPosition', 'getShape', 'getTitle', + 'getVisible', 'getZIndex' + ]); + markerSpy.addListener.and.returnValue({remove: () => {}}); + return markerSpy; } /** Creates a jasmine.Spy to watch for the constructor of a google.maps.Marker */ -export function createMarkerConstructorSpy(markerSpy: jasmine.SpyObj): jasmine.Spy { - const markerConstructorSpy = jasmine.createSpy('Marker constructor', (_options: google.maps.MarkerOptions) => { - return markerSpy; - }); +export function createMarkerConstructorSpy(markerSpy: jasmine.SpyObj): + jasmine.Spy { + const markerConstructorSpy = + jasmine.createSpy('Marker constructor', (_options: google.maps.MarkerOptions) => { + return markerSpy; + }); + const testingWindow: TestingWindow = window; testingWindow.google = { maps: { 'Marker': markerConstructorSpy, From 6ce4ae07d0c769d5d81a749bbac3e5c6ba62c0fb Mon Sep 17 00:00:00 2001 From: Matthew Ehrlich Date: Tue, 3 Sep 2019 14:00:18 -0700 Subject: [PATCH 4/9] feat(google-maps): Add google-map-marker component Fix bug with demo bazel file and with fake data for marker test. --- src/dev-app/google-map/BUILD.bazel | 1 + src/google-maps/google-map-marker/google-map-marker.spec.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dev-app/google-map/BUILD.bazel b/src/dev-app/google-map/BUILD.bazel index 00302ae45f41..3f8916e888d9 100644 --- a/src/dev-app/google-map/BUILD.bazel +++ b/src/dev-app/google-map/BUILD.bazel @@ -8,6 +8,7 @@ ng_module( assets = ["google-map-demo.html"], deps = [ "//src/google-maps/google-map", + "//src/google-maps/google-map-marker", "@npm//@angular/router", ], ) diff --git a/src/google-maps/google-map-marker/google-map-marker.spec.ts b/src/google-maps/google-map-marker/google-map-marker.spec.ts index 6a3de80ad9b7..b90b969f1e87 100644 --- a/src/google-maps/google-map-marker/google-map-marker.spec.ts +++ b/src/google-maps/google-map-marker/google-map-marker.spec.ts @@ -177,8 +177,8 @@ describe('GoogleMapMarker', () => { markerSpy.getIcon.and.returnValue('icon'); expect(markerComponent.getIcon()).toBe('icon'); - markerSpy.getLabel.and.returnValue('label'); - expect(markerComponent.getLabel()).toBe('label'); + markerSpy.getLabel.and.returnValue(null); + expect(markerComponent.getLabel()).toBe(null); markerSpy.getOpacity.and.returnValue(5); expect(markerComponent.getOpacity()).toBe(5); From 8b7c083e35a87f39c4803d35a636c85a1af1f8f6 Mon Sep 17 00:00:00 2001 From: Matthew Ehrlich Date: Thu, 5 Sep 2019 19:33:51 -0700 Subject: [PATCH 5/9] feat(google-maps): Add map-marker component Make various fixes internal cleanup fixes. Change google-map-marker to map-marker. Use QueryList's changes property instead of a setter for ContentChildren. --- packages.bzl | 1 - src/dev-app/google-map/BUILD.bazel | 1 - .../google-map/google-map-demo-module.ts | 2 - src/dev-app/google-map/google-map-demo.html | 9 ++- src/dev-app/google-map/google-map-demo.ts | 8 +- src/dev-app/system-config.js | 1 - src/google-maps/BUILD.bazel | 1 + .../google-map-marker/google-map-marker.md | 0 .../google-map-marker/public-api.ts | 10 --- .../google-map-marker/tsconfig-build.json | 15 ---- src/google-maps/google-map/BUILD.bazel | 4 +- .../google-map/google-map-module.ts | 19 +++-- src/google-maps/google-map/google-map.spec.ts | 13 ++- src/google-maps/google-map/google-map.ts | 39 +++++---- .../BUILD.bazel | 11 +-- .../index.ts | 3 +- .../map-marker-module.ts} | 9 ++- .../map-marker.spec.ts} | 81 +++++++++---------- .../map-marker.ts} | 21 +++-- src/google-maps/public-api.ts | 2 +- 20 files changed, 115 insertions(+), 135 deletions(-) delete mode 100644 src/google-maps/google-map-marker/google-map-marker.md delete mode 100644 src/google-maps/google-map-marker/public-api.ts delete mode 100644 src/google-maps/google-map-marker/tsconfig-build.json rename src/google-maps/{google-map-marker => map-marker}/BUILD.bazel (76%) rename src/google-maps/{google-map-marker => map-marker}/index.ts (75%) rename src/google-maps/{google-map-marker/google-map-marker-module.ts => map-marker/map-marker-module.ts} (62%) rename src/google-maps/{google-map-marker/google-map-marker.spec.ts => map-marker/map-marker.spec.ts} (75%) rename src/google-maps/{google-map-marker/google-map-marker.ts => map-marker/map-marker.ts} (96%) diff --git a/packages.bzl b/packages.bzl index 54d7ce0cf41d..f0cf5c7d29c7 100644 --- a/packages.bzl +++ b/packages.bzl @@ -82,7 +82,6 @@ MATERIAL_SCSS_LIBS = [ GOOGLE_MAPS_PACKAGES = [ "google-map", - "google-map-marker", ] GOOGLE_MAPS_TARGETS = ["//src/google-maps"] + ["//src/google-maps/%s" % p for p in GOOGLE_MAPS_PACKAGES] diff --git a/src/dev-app/google-map/BUILD.bazel b/src/dev-app/google-map/BUILD.bazel index 3f8916e888d9..00302ae45f41 100644 --- a/src/dev-app/google-map/BUILD.bazel +++ b/src/dev-app/google-map/BUILD.bazel @@ -8,7 +8,6 @@ ng_module( assets = ["google-map-demo.html"], deps = [ "//src/google-maps/google-map", - "//src/google-maps/google-map-marker", "@npm//@angular/router", ], ) diff --git a/src/dev-app/google-map/google-map-demo-module.ts b/src/dev-app/google-map/google-map-demo-module.ts index 6a3bea0644d1..5473fb36884c 100644 --- a/src/dev-app/google-map/google-map-demo-module.ts +++ b/src/dev-app/google-map/google-map-demo-module.ts @@ -10,7 +10,6 @@ import {CommonModule} from '@angular/common'; import {HttpClientJsonpModule, HttpClientModule} from '@angular/common/http'; import {NgModule} from '@angular/core'; import {GoogleMapModule} from '@angular/google-maps/google-map'; -import {GoogleMapMarkerModule} from '@angular/google-maps/google-map-marker'; import {RouterModule} from '@angular/router'; import {GoogleMapDemo} from './google-map-demo'; @@ -19,7 +18,6 @@ import {GoogleMapDemo} from './google-map-demo'; imports: [ CommonModule, GoogleMapModule, - GoogleMapMarkerModule, HttpClientJsonpModule, HttpClientModule, RouterModule.forChild([{path: '', component: GoogleMapDemo}]), diff --git a/src/dev-app/google-map/google-map-demo.html b/src/dev-app/google-map/google-map-demo.html index c55e49239272..588e0a77432d 100644 --- a/src/dev-app/google-map/google-map-demo.html +++ b/src/dev-app/google-map/google-map-demo.html @@ -4,10 +4,13 @@ [center]="center" [zoom]="zoom" (mapClick)="handleClick($event)" - (mapMousemove)="handleMove($event)"> - + + + (mapClick)="clickMarker($event)">
Latitude: {{display?.lat}}
diff --git a/src/dev-app/google-map/google-map-demo.ts b/src/dev-app/google-map/google-map-demo.ts index 9f454e9ea5cf..163c8573f39e 100644 --- a/src/dev-app/google-map/google-map-demo.ts +++ b/src/dev-app/google-map/google-map-demo.ts @@ -20,7 +20,7 @@ export class GoogleMapDemo { center = {lat: 24, lng: 12}; markerOptions = {draggable: false}; - markerPosition = {lat: 39.830205, lng: -77.232949}; + markerPositions: google.maps.LatLngLiteral[] = []; zoom = 4; display?: google.maps.LatLngLiteral; @@ -32,7 +32,7 @@ export class GoogleMapDemo { } handleClick(event: google.maps.MouseEvent) { - this.center = event.latLng.toJSON(); + this.markerPositions.push(event.latLng.toJSON()); } handleMove(event: google.maps.MouseEvent) { @@ -43,4 +43,8 @@ export class GoogleMapDemo { console.log(this.markerOptions); this.markerOptions = {draggable: true}; } + + handleRightclick() { + this.markerPositions.pop(); + } } diff --git a/src/dev-app/system-config.js b/src/dev-app/system-config.js index d792ce80fee1..ea418484e985 100644 --- a/src/dev-app/system-config.js +++ b/src/dev-app/system-config.js @@ -57,7 +57,6 @@ var MATERIAL_PACKAGES = [ var GOOGLE_MAPS_PACKAGES = [ 'google-map', - 'google-map-marker', ]; var MATERIAL_EXPERIMENTAL_PACKAGES = [ diff --git a/src/google-maps/BUILD.bazel b/src/google-maps/BUILD.bazel index c1dcec127f86..c0c29b95dcb3 100644 --- a/src/google-maps/BUILD.bazel +++ b/src/google-maps/BUILD.bazel @@ -12,6 +12,7 @@ ng_module( ), module_name = "@angular/google-maps", deps = ["//src/google-maps/%s" % p for p in GOOGLE_MAPS_PACKAGES] + [ + "//src/google-maps/map-marker", "@npm//@angular/core", "@npm//@types/googlemaps", ], diff --git a/src/google-maps/google-map-marker/google-map-marker.md b/src/google-maps/google-map-marker/google-map-marker.md deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/src/google-maps/google-map-marker/public-api.ts b/src/google-maps/google-map-marker/public-api.ts deleted file mode 100644 index a4062d292728..000000000000 --- a/src/google-maps/google-map-marker/public-api.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -export * from './google-map-marker-module'; -export * from './google-map-marker'; diff --git a/src/google-maps/google-map-marker/tsconfig-build.json b/src/google-maps/google-map-marker/tsconfig-build.json deleted file mode 100644 index 3eccc179e82c..000000000000 --- a/src/google-maps/google-map-marker/tsconfig-build.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "../tsconfig-build", - "files": [ - "public-api.ts", - "../typings.d.ts" - ], - "angularCompilerOptions": { - "annotateForClosureCompiler": true, - "strictMetadataEmit": true, - "flatModuleOutFile": "index.js", - "flatModuleId": "@angular/google-maps/google-map-marker", - "skipTemplateCodegen": true, - "fullTemplateTypeCheck": true - } -} diff --git a/src/google-maps/google-map/BUILD.bazel b/src/google-maps/google-map/BUILD.bazel index ed141523cfc3..09adb1212d70 100644 --- a/src/google-maps/google-map/BUILD.bazel +++ b/src/google-maps/google-map/BUILD.bazel @@ -16,7 +16,7 @@ ng_module( ), module_name = "@angular/google-maps/google-map", deps = [ - "//src/google-maps/google-map-marker", + "//src/google-maps/map-marker", "@npm//@angular/core", "@npm//@types/googlemaps", "@npm//rxjs", @@ -31,7 +31,7 @@ ng_test_library( ), deps = [ ":google-map", - "//src/google-maps/google-map-marker", + "//src/google-maps/map-marker", "//src/google-maps/testing", "@npm//@angular/platform-browser", ], diff --git a/src/google-maps/google-map/google-map-module.ts b/src/google-maps/google-map/google-map-module.ts index 3d4c69dc21e9..3e41ead5c9f9 100644 --- a/src/google-maps/google-map/google-map-module.ts +++ b/src/google-maps/google-map/google-map-module.ts @@ -6,11 +6,16 @@ * found in the LICENSE file at https://angular.io/license */ - import {NgModule} from '@angular/core'; - import {GoogleMap} from './google-map'; +import {NgModule} from '@angular/core'; - @NgModule({ - exports: [GoogleMap], - declarations: [GoogleMap], - }) - export class GoogleMapModule {} +import {MapMarker, MapMarkerModule} from '../map-marker/index'; + +import {GoogleMap} from './google-map'; + +@NgModule({ + imports: [MapMarkerModule], + exports: [GoogleMap, MapMarker], + declarations: [GoogleMap], +}) +export class GoogleMapModule { +} diff --git a/src/google-maps/google-map/google-map.spec.ts b/src/google-maps/google-map/google-map.spec.ts index 1c1fcfa6ca58..f3de7fc8ac95 100644 --- a/src/google-maps/google-map/google-map.spec.ts +++ b/src/google-maps/google-map/google-map.spec.ts @@ -2,7 +2,7 @@ import {Component} from '@angular/core'; import {async, TestBed} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; -import {GoogleMapMarker, GoogleMapMarkerModule} from '../google-map-marker/index'; +import {MapMarker, MapMarkerModule} from '../map-marker/index'; import { createMapConstructorSpy, createMapSpy, @@ -40,7 +40,7 @@ describe('GoogleMap', () => { TestBed.configureTestingModule({ imports: [ GoogleMapModule, - GoogleMapMarkerModule, + MapMarkerModule, ], declarations: [TestApp], }); @@ -248,12 +248,11 @@ describe('GoogleMap', () => { createMapConstructorSpy(mapSpy).and.callThrough(); const fixture = TestBed.createComponent(TestApp); - const markerComponent = - fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; - spyOn(markerComponent, 'setMap').and.callThrough(); + const markerComponent = fixture.debugElement.query(By.directive(MapMarker)).componentInstance; + spyOn(markerComponent, '_setMap').and.callThrough(); fixture.detectChanges(); - expect(markerComponent.setMap).toHaveBeenCalledWith(mapSpy); + expect(markerComponent._setMap).toHaveBeenCalledWith(mapSpy); }); }); @@ -267,7 +266,7 @@ describe('GoogleMap', () => { (mapClick)="handleClick($event)" (centerChanged)="handleCenterChanged()" (mapRightclick)="handleRightclick($event)"> - + `, }) class TestApp { diff --git a/src/google-maps/google-map/google-map.ts b/src/google-maps/google-map/google-map.ts index 867e08386eff..6c3021434248 100644 --- a/src/google-maps/google-map/google-map.ts +++ b/src/google-maps/google-map/google-map.ts @@ -1,4 +1,5 @@ import { + AfterContentInit, ChangeDetectionStrategy, Component, ContentChildren, @@ -11,9 +12,10 @@ import { Output, QueryList, } from '@angular/core'; +import {BehaviorSubject, combineLatest, Observable, Subject} from 'rxjs'; import {map, shareReplay, take, takeUntil} from 'rxjs/operators'; -import {BehaviorSubject, combineLatest, Observable, ReplaySubject, Subject} from 'rxjs'; -import {GoogleMapMarker} from '@angular/google-maps/google-map-marker'; + +import {MapMarker} from '../map-marker/index'; interface GoogleMapsWindow extends Window { google?: typeof google; @@ -49,7 +51,7 @@ export const DEFAULT_WIDTH = '500px'; changeDetection: ChangeDetectionStrategy.OnPush, template: '
', }) -export class GoogleMap implements OnChanges, OnInit, OnDestroy { +export class GoogleMap implements OnChanges, OnInit, AfterContentInit, OnDestroy { @Input() height = DEFAULT_HEIGHT; @Input() width = DEFAULT_WIDTH; @@ -175,21 +177,19 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy { */ @Output() zoomChanged = new EventEmitter(); - @ContentChildren(GoogleMapMarker) set markers(markers: QueryList) { - this._markers.next(markers.toArray()); - } + @ContentChildren(MapMarker) _markers: QueryList; private _mapEl: HTMLElement; private _googleMap!: UpdatedGoogleMap; + private _googleMapChanges!: Observable; + private readonly _listeners: google.maps.MapsEventListener[] = []; private readonly _options = new BehaviorSubject(DEFAULT_OPTIONS); private readonly _center = new BehaviorSubject(undefined); private readonly _zoom = new BehaviorSubject(undefined); - private readonly _markers = new ReplaySubject(1); - private readonly _destroy = new Subject(); constructor(private readonly _elementRef: ElementRef) { @@ -213,15 +213,21 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy { const combinedOptionsChanges = this._combineOptions(); - const googleMapChanges = this._initializeMap(combinedOptionsChanges); - googleMapChanges.subscribe((googleMap: google.maps.Map) => { + this._googleMapChanges = this._initializeMap(combinedOptionsChanges); + this._googleMapChanges.subscribe((googleMap: google.maps.Map) => { this._googleMap = googleMap as UpdatedGoogleMap; + this._initializeEventHandlers(); }); - this._watchForOptionsChanges(googleMapChanges, combinedOptionsChanges); + this._watchForOptionsChanges(combinedOptionsChanges); + } - this._watchForMarkerChanges(googleMapChanges); + ngAfterContentInit() { + for (const marker of this._markers.toArray()) { + marker._setMap(this._googleMap); + } + this._watchForMarkerChanges(); } ngOnDestroy() { @@ -402,9 +408,8 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy { } private _watchForOptionsChanges( - googleMapChanges: Observable, optionsChanges: Observable) { - combineLatest(googleMapChanges, optionsChanges) + combineLatest(this._googleMapChanges, optionsChanges) .pipe(takeUntil(this._destroy)) .subscribe(([googleMap, options]) => { googleMap.setOptions(options); @@ -457,12 +462,12 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy { } } - private _watchForMarkerChanges(googleMapChanges: Observable) { - combineLatest(googleMapChanges, this._markers) + private _watchForMarkerChanges() { + combineLatest(this._googleMapChanges, this._markers.changes) .pipe(takeUntil(this._destroy)) .subscribe(([googleMap, markers]) => { for (let marker of markers) { - marker.setMap(googleMap); + marker._setMap(googleMap); } }); } diff --git a/src/google-maps/google-map-marker/BUILD.bazel b/src/google-maps/map-marker/BUILD.bazel similarity index 76% rename from src/google-maps/google-map-marker/BUILD.bazel rename to src/google-maps/map-marker/BUILD.bazel index 1f6614bbf8a9..65d075a3dfe0 100644 --- a/src/google-maps/google-map-marker/BUILD.bazel +++ b/src/google-maps/map-marker/BUILD.bazel @@ -2,19 +2,17 @@ package(default_visibility = ["//visibility:public"]) load( "//tools:defaults.bzl", - "markdown_to_html", "ng_module", "ng_test_library", "ng_web_test_suite", ) ng_module( - name = "google-map-marker", + name = "map-marker", srcs = glob( ["**/*.ts"], exclude = ["**/*.spec.ts"], ), - module_name = "@angular/google-maps/google-map-marker", deps = [ "@npm//@angular/core", "@npm//@types/googlemaps", @@ -29,7 +27,7 @@ ng_test_library( exclude = ["**/*.e2e.spec.ts"], ), deps = [ - ":google-map-marker", + ":map-marker", "//src/google-maps/testing", "@npm//@angular/platform-browser", ], @@ -40,11 +38,6 @@ ng_web_test_suite( deps = [":unit_test_sources"], ) -markdown_to_html( - name = "overview", - srcs = [":google-map-marker.md"], -) - filegroup( name = "source-files", srcs = glob(["**/*.ts"]), diff --git a/src/google-maps/google-map-marker/index.ts b/src/google-maps/map-marker/index.ts similarity index 75% rename from src/google-maps/google-map-marker/index.ts rename to src/google-maps/map-marker/index.ts index 676ca90f1ffa..6e68afdc7e09 100644 --- a/src/google-maps/google-map-marker/index.ts +++ b/src/google-maps/map-marker/index.ts @@ -6,4 +6,5 @@ * found in the LICENSE file at https://angular.io/license */ -export * from './public-api'; +export * from './map-marker'; +export * from './map-marker-module'; diff --git a/src/google-maps/google-map-marker/google-map-marker-module.ts b/src/google-maps/map-marker/map-marker-module.ts similarity index 62% rename from src/google-maps/google-map-marker/google-map-marker-module.ts rename to src/google-maps/map-marker/map-marker-module.ts index 4805c379e713..6752cd28eae8 100644 --- a/src/google-maps/google-map-marker/google-map-marker-module.ts +++ b/src/google-maps/map-marker/map-marker-module.ts @@ -7,10 +7,11 @@ */ import {NgModule} from '@angular/core'; -import {GoogleMapMarker} from './google-map-marker'; +import {MapMarker} from './map-marker'; @NgModule({ - exports: [GoogleMapMarker], - declarations: [GoogleMapMarker], + exports: [MapMarker], + declarations: [MapMarker], }) -export class GoogleMapMarkerModule { } +export class MapMarkerModule { +} diff --git a/src/google-maps/google-map-marker/google-map-marker.spec.ts b/src/google-maps/map-marker/map-marker.spec.ts similarity index 75% rename from src/google-maps/google-map-marker/google-map-marker.spec.ts rename to src/google-maps/map-marker/map-marker.spec.ts index b90b969f1e87..28b53c1925c2 100644 --- a/src/google-maps/google-map-marker/google-map-marker.spec.ts +++ b/src/google-maps/map-marker/map-marker.spec.ts @@ -8,12 +8,12 @@ import { TestingWindow } from '../testing/fake-google-map-utils'; -import {DEFAULT_MARKER_OPTIONS, GoogleMapMarker, GoogleMapMarkerModule} from './index'; +import {DEFAULT_MARKER_OPTIONS, MapMarker, MapMarkerModule} from './index'; -describe('GoogleMapMarker', () => { +describe('MapMarker', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [GoogleMapMarkerModule], + imports: [MapMarkerModule], declarations: [TestApp], }); })); @@ -28,14 +28,13 @@ describe('GoogleMapMarker', () => { }); it('initializes a Google Map marker', () => { - let markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); - let markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); + const markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); + const markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); const fixture = TestBed.createComponent(TestApp); const fakeMap = {} as unknown as google.maps.Map; - const markerComponent = - fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; - markerComponent.setMap(fakeMap); + const markerComponent = fixture.debugElement.query(By.directive(MapMarker)).componentInstance; + markerComponent._setMap(fakeMap); fixture.detectChanges(); expect(markerConstructorSpy).toHaveBeenCalledWith({ @@ -56,17 +55,16 @@ describe('GoogleMapMarker', () => { clickable: false, map: fakeMap, }; - let markerSpy = createMarkerSpy(options); - let markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); + const markerSpy = createMarkerSpy(options); + const markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); const fixture = TestBed.createComponent(TestApp); fixture.componentInstance.position = options.position; fixture.componentInstance.title = options.title; fixture.componentInstance.label = options.label; fixture.componentInstance.clickable = options.clickable; - const markerComponent = - fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; - markerComponent.setMap(fakeMap); + const markerComponent = fixture.debugElement.query(By.directive(MapMarker)).componentInstance; + markerComponent._setMap(fakeMap); fixture.detectChanges(); expect(markerConstructorSpy).toHaveBeenCalledWith(options); @@ -81,14 +79,13 @@ describe('GoogleMapMarker', () => { clickable: false, icon: 'icon name', }; - let markerSpy = createMarkerSpy(options); - let markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); + const markerSpy = createMarkerSpy(options); + const markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); const fixture = TestBed.createComponent(TestApp); fixture.componentInstance.options = options; - const markerComponent = - fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; - markerComponent.setMap(fakeMap); + const markerComponent = fixture.debugElement.query(By.directive(MapMarker)).componentInstance; + markerComponent._setMap(fakeMap); fixture.detectChanges(); expect(markerConstructorSpy).toHaveBeenCalledWith({...options, map: fakeMap}); @@ -111,8 +108,8 @@ describe('GoogleMapMarker', () => { icon: 'icon name', map: fakeMap, }; - let markerSpy = createMarkerSpy(options); - let markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); + const markerSpy = createMarkerSpy(options); + const markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); const fixture = TestBed.createComponent(TestApp); fixture.componentInstance.position = expectedOptions.position; @@ -120,25 +117,23 @@ describe('GoogleMapMarker', () => { fixture.componentInstance.label = expectedOptions.label; fixture.componentInstance.clickable = expectedOptions.clickable; fixture.componentInstance.options = options; - const markerComponent = - fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; - markerComponent.setMap(fakeMap); + const markerComponent = fixture.debugElement.query(By.directive(MapMarker)).componentInstance; + markerComponent._setMap(fakeMap); fixture.detectChanges(); expect(markerConstructorSpy).toHaveBeenCalledWith(expectedOptions); }); it('sets the map on the marker only once', () => { - let markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); - let markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); + const markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); + const markerConstructorSpy = createMarkerConstructorSpy(markerSpy).and.callThrough(); const fixture = TestBed.createComponent(TestApp); const fakeMap = {} as unknown as google.maps.Map; const fakeMap2 = {testValue: 'test'} as unknown as google.maps.Map; - const markerComponent = - fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; - markerComponent.setMap(fakeMap); - markerComponent.setMap(fakeMap2); + const markerComponent = fixture.debugElement.query(By.directive(MapMarker)).componentInstance; + markerComponent._setMap(fakeMap); + markerComponent._setMap(fakeMap2); fixture.detectChanges(); expect(markerConstructorSpy).toHaveBeenCalledWith({ @@ -152,14 +147,13 @@ describe('GoogleMapMarker', () => { }); it('exposes methods that provide information about the marker', () => { - let markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); + const markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); createMarkerConstructorSpy(markerSpy).and.callThrough(); const fixture = TestBed.createComponent(TestApp); const fakeMap = {} as unknown as google.maps.Map; - const markerComponent = - fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; - markerComponent.setMap(fakeMap); + const markerComponent = fixture.debugElement.query(By.directive(MapMarker)).componentInstance; + markerComponent._setMap(fakeMap); fixture.detectChanges(); markerSpy.getAnimation.and.returnValue(null); @@ -200,14 +194,13 @@ describe('GoogleMapMarker', () => { }); it('initializes marker event handlers', () => { - let markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); + const markerSpy = createMarkerSpy(DEFAULT_MARKER_OPTIONS); createMarkerConstructorSpy(markerSpy).and.callThrough(); const fixture = TestBed.createComponent(TestApp); const fakeMap = {} as unknown as google.maps.Map; - const markerComponent = - fixture.debugElement.query(By.directive(GoogleMapMarker)).componentInstance; - markerComponent.setMap(fakeMap); + const markerComponent = fixture.debugElement.query(By.directive(MapMarker)).componentInstance; + markerComponent._setMap(fakeMap); fixture.detectChanges(); expect(markerSpy.addListener) @@ -240,13 +233,13 @@ describe('GoogleMapMarker', () => { @Component({ selector: 'test-app', - template: ``, + template: ``, }) class TestApp { title?: string; diff --git a/src/google-maps/google-map-marker/google-map-marker.ts b/src/google-maps/map-marker/map-marker.ts similarity index 96% rename from src/google-maps/google-map-marker/google-map-marker.ts rename to src/google-maps/map-marker/map-marker.ts index 3adde5b687ec..6117481e9caf 100644 --- a/src/google-maps/google-map-marker/google-map-marker.ts +++ b/src/google-maps/map-marker/map-marker.ts @@ -23,28 +23,33 @@ export const DEFAULT_MARKER_OPTIONS = { * @see developers.google.com/maps/documentation/javascript/reference/marker */ @Component({ - selector: 'google-map-marker', + selector: 'map-marker', template: '', changeDetection: ChangeDetectionStrategy.OnPush, }) -export class GoogleMapMarker implements OnInit, OnDestroy { - @Input() set options(options: google.maps.MarkerOptions) { +export class MapMarker implements OnInit, OnDestroy { + @Input() + set options(options: google.maps.MarkerOptions) { this._options.next(options || DEFAULT_MARKER_OPTIONS); } - @Input() set title(title: string) { + @Input() + set title(title: string) { this._title.next(title); } - @Input() set position(position: google.maps.LatLngLiteral) { + @Input() + set position(position: google.maps.LatLngLiteral) { this._position.next(position); } - @Input() set label(label: string|google.maps.MarkerLabel) { + @Input() + set label(label: string|google.maps.MarkerLabel) { this._label.next(label); } - @Input() set clickable(clickable: boolean) { + @Input() + set clickable(clickable: boolean) { this._clickable.next(clickable); } @@ -218,7 +223,7 @@ export class GoogleMapMarker implements OnInit, OnDestroy { } } - setMap(googleMap: google.maps.Map) { + _setMap(googleMap: google.maps.Map) { if (!this._hasMap) { this._map.next(googleMap); this._hasMap = true; diff --git a/src/google-maps/public-api.ts b/src/google-maps/public-api.ts index a1a6a64c2279..ae8a3ce74f9d 100644 --- a/src/google-maps/public-api.ts +++ b/src/google-maps/public-api.ts @@ -7,4 +7,4 @@ */ export * from '@angular/google-maps/google-map'; -export * from '@angular/google-maps/google-map-marker'; +export {MapMarker} from './map-marker/map-marker'; From 047c3f84cb45485614c8c6aa7e8b4a6e05cc6aeb Mon Sep 17 00:00:00 2001 From: Matthew Ehrlich Date: Fri, 6 Sep 2019 11:45:17 -0700 Subject: [PATCH 6/9] feat(google-maps): Add map-marker component Fix type bug with map marker tests. --- src/google-maps/map-marker/map-marker.spec.ts | 4 ++-- src/google-maps/public-api.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/google-maps/map-marker/map-marker.spec.ts b/src/google-maps/map-marker/map-marker.spec.ts index 28b53c1925c2..047fe764b02f 100644 --- a/src/google-maps/map-marker/map-marker.spec.ts +++ b/src/google-maps/map-marker/map-marker.spec.ts @@ -177,8 +177,8 @@ describe('MapMarker', () => { markerSpy.getOpacity.and.returnValue(5); expect(markerComponent.getOpacity()).toBe(5); - markerSpy.getPosition.and.returnValue({lat: 1, lng: 2}); - expect(markerComponent.getPosition()).toEqual({lat: 1, lng: 2}); + markerSpy.getPosition.and.returnValue(null); + expect(markerComponent.getPosition()).toEqual(null); markerSpy.getShape.and.returnValue(null); expect(markerComponent.getShape()).toBe(null); diff --git a/src/google-maps/public-api.ts b/src/google-maps/public-api.ts index ae8a3ce74f9d..9d11682064d7 100644 --- a/src/google-maps/public-api.ts +++ b/src/google-maps/public-api.ts @@ -7,4 +7,3 @@ */ export * from '@angular/google-maps/google-map'; -export {MapMarker} from './map-marker/map-marker'; From 17229514613192340b50a8d9a3255ce537d62fac Mon Sep 17 00:00:00 2001 From: Matthew Ehrlich Date: Fri, 6 Sep 2019 14:32:45 -0700 Subject: [PATCH 7/9] feat(google-maps): Add map-marker component Refactor google-maps module to have a single entry-point, @angular/google-maps, instead of a separate one for every component. --- packages.bzl | 6 ------ src/dev-app/google-map/BUILD.bazel | 2 +- .../google-map/google-map-demo-module.ts | 4 ++-- src/dev-app/system-config.js | 8 +------- src/dev-app/tsconfig.json | 2 +- src/google-maps/BUILD.bazel | 17 ++++++++-------- src/google-maps/google-map/BUILD.bazel | 7 ------- .../google-map/google-map-module.ts | 5 +---- src/google-maps/google-map/google-map.md | 0 src/google-maps/google-map/index.ts | 3 ++- src/google-maps/google-map/public-api.ts | 10 ---------- .../google-map/tsconfig-build.json | 15 -------------- src/google-maps/google-maps-module.ts | 20 +++++++++++++++++++ src/google-maps/index.ts | 2 +- src/google-maps/public-api.ts | 4 +++- src/google-maps/tsconfig-build.json | 3 --- src/google-maps/tsconfig-tests.json | 3 --- src/google-maps/tsconfig.json | 4 +--- 18 files changed, 42 insertions(+), 73 deletions(-) delete mode 100644 src/google-maps/google-map/google-map.md delete mode 100644 src/google-maps/google-map/public-api.ts delete mode 100644 src/google-maps/google-map/tsconfig-build.json create mode 100644 src/google-maps/google-maps-module.ts diff --git a/packages.bzl b/packages.bzl index f0cf5c7d29c7..7e5eace774be 100644 --- a/packages.bzl +++ b/packages.bzl @@ -80,12 +80,6 @@ MATERIAL_SCSS_LIBS = [ for p in MATERIAL_PACKAGES ] -GOOGLE_MAPS_PACKAGES = [ - "google-map", -] - -GOOGLE_MAPS_TARGETS = ["//src/google-maps"] + ["//src/google-maps/%s" % p for p in GOOGLE_MAPS_PACKAGES] - MATERIAL_EXPERIMENTAL_PACKAGES = [ "mdc-button", "mdc-card", diff --git a/src/dev-app/google-map/BUILD.bazel b/src/dev-app/google-map/BUILD.bazel index 00302ae45f41..3b0c062cb3b3 100644 --- a/src/dev-app/google-map/BUILD.bazel +++ b/src/dev-app/google-map/BUILD.bazel @@ -7,7 +7,7 @@ ng_module( srcs = glob(["**/*.ts"]), assets = ["google-map-demo.html"], deps = [ - "//src/google-maps/google-map", + "//src/google-maps", "@npm//@angular/router", ], ) diff --git a/src/dev-app/google-map/google-map-demo-module.ts b/src/dev-app/google-map/google-map-demo-module.ts index 5473fb36884c..aeaaeeb31f28 100644 --- a/src/dev-app/google-map/google-map-demo-module.ts +++ b/src/dev-app/google-map/google-map-demo-module.ts @@ -9,7 +9,7 @@ import {CommonModule} from '@angular/common'; import {HttpClientJsonpModule, HttpClientModule} from '@angular/common/http'; import {NgModule} from '@angular/core'; -import {GoogleMapModule} from '@angular/google-maps/google-map'; +import {GoogleMapsModule} from '@angular/google-maps'; import {RouterModule} from '@angular/router'; import {GoogleMapDemo} from './google-map-demo'; @@ -17,7 +17,7 @@ import {GoogleMapDemo} from './google-map-demo'; @NgModule({ imports: [ CommonModule, - GoogleMapModule, + GoogleMapsModule, HttpClientJsonpModule, HttpClientModule, RouterModule.forChild([{path: '', component: GoogleMapDemo}]), diff --git a/src/dev-app/system-config.js b/src/dev-app/system-config.js index ea418484e985..14b940b34b72 100644 --- a/src/dev-app/system-config.js +++ b/src/dev-app/system-config.js @@ -55,10 +55,6 @@ var MATERIAL_PACKAGES = [ 'tree', ]; -var GOOGLE_MAPS_PACKAGES = [ - 'google-map', -]; - var MATERIAL_EXPERIMENTAL_PACKAGES = [ 'mdc-button', 'mdc-card', @@ -103,9 +99,7 @@ MATERIAL_EXPERIMENTAL_PACKAGES.forEach(function(pkgName) { MATERIAL_PACKAGES.forEach(function(pkgName) { configureEntryPoint('material', pkgName); }); -GOOGLE_MAPS_PACKAGES.forEach(function(pkgName) { - configureEntryPoint('google-maps', pkgName); -}); +configureEntryPoint('google-maps'); configureEntryPoint('youtube-player'); /** Configures the specified package and its entry-point. */ diff --git a/src/dev-app/tsconfig.json b/src/dev-app/tsconfig.json index 74ead8d0563b..abeff4c04762 100644 --- a/src/dev-app/tsconfig.json +++ b/src/dev-app/tsconfig.json @@ -14,7 +14,7 @@ "@angular/cdk-experimental/*": ["../cdk-experimental/*"], "@angular/cdk-experimental": ["../cdk-experimental"], "@angular/material-moment-adapter": ["../material-moment-adapter/public-api.ts"], - "@angular/google-maps/*": ["../google-maps/*"], + "@angular/google-maps": ["../google-maps"], "@angular/material-examples": ["../../dist/packages/material-examples"] } }, diff --git a/src/google-maps/BUILD.bazel b/src/google-maps/BUILD.bazel index c0c29b95dcb3..9887c83162a0 100644 --- a/src/google-maps/BUILD.bazel +++ b/src/google-maps/BUILD.bazel @@ -1,6 +1,6 @@ package(default_visibility = ["//visibility:public"]) -load("//:packages.bzl", "GOOGLE_MAPS_PACKAGES", "GOOGLE_MAPS_TARGETS", "ROLLUP_GLOBALS") +load("//:packages.bzl", "ROLLUP_GLOBALS") load("//tools:defaults.bzl", "ng_module", "ng_package") # Root "@angular/google-maps" entry-point that does not re-export individual entry-points. @@ -11,18 +11,14 @@ ng_module( exclude = ["**/*.spec.ts"], ), module_name = "@angular/google-maps", - deps = ["//src/google-maps/%s" % p for p in GOOGLE_MAPS_PACKAGES] + [ + deps = [ + "//src/google-maps/google-map", "//src/google-maps/map-marker", "@npm//@angular/core", "@npm//@types/googlemaps", ], ) -filegroup( - name = "overviews", - srcs = ["//src/google-maps/%s:overview" % name for name in GOOGLE_MAPS_PACKAGES], -) - # Creates the @angular/google-maps package published to npm ng_package( name = "npm_package", @@ -30,5 +26,10 @@ ng_package( entry_point = ":public-api.ts", entry_point_name = "google-maps", globals = ROLLUP_GLOBALS, - deps = GOOGLE_MAPS_TARGETS, + deps = [":google-maps"], +) + +filegroup( + name = "source-files", + srcs = glob(["**/*.ts"]), ) diff --git a/src/google-maps/google-map/BUILD.bazel b/src/google-maps/google-map/BUILD.bazel index 09adb1212d70..2a0e523a379f 100644 --- a/src/google-maps/google-map/BUILD.bazel +++ b/src/google-maps/google-map/BUILD.bazel @@ -2,7 +2,6 @@ package(default_visibility = ["//visibility:public"]) load( "//tools:defaults.bzl", - "markdown_to_html", "ng_module", "ng_test_library", "ng_web_test_suite", @@ -14,7 +13,6 @@ ng_module( ["**/*.ts"], exclude = ["**/*.spec.ts"], ), - module_name = "@angular/google-maps/google-map", deps = [ "//src/google-maps/map-marker", "@npm//@angular/core", @@ -42,11 +40,6 @@ ng_web_test_suite( deps = [":unit_test_sources"], ) -markdown_to_html( - name = "overview", - srcs = [":google-map.md"], -) - filegroup( name = "source-files", srcs = glob(["**/*.ts"]), diff --git a/src/google-maps/google-map/google-map-module.ts b/src/google-maps/google-map/google-map-module.ts index 3e41ead5c9f9..486899c06199 100644 --- a/src/google-maps/google-map/google-map-module.ts +++ b/src/google-maps/google-map/google-map-module.ts @@ -8,13 +8,10 @@ import {NgModule} from '@angular/core'; -import {MapMarker, MapMarkerModule} from '../map-marker/index'; - import {GoogleMap} from './google-map'; @NgModule({ - imports: [MapMarkerModule], - exports: [GoogleMap, MapMarker], + exports: [GoogleMap], declarations: [GoogleMap], }) export class GoogleMapModule { diff --git a/src/google-maps/google-map/google-map.md b/src/google-maps/google-map/google-map.md deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/src/google-maps/google-map/index.ts b/src/google-maps/google-map/index.ts index 676ca90f1ffa..34b16fbeddf7 100644 --- a/src/google-maps/google-map/index.ts +++ b/src/google-maps/google-map/index.ts @@ -6,4 +6,5 @@ * found in the LICENSE file at https://angular.io/license */ -export * from './public-api'; +export * from './google-map'; +export * from './google-map-module'; diff --git a/src/google-maps/google-map/public-api.ts b/src/google-maps/google-map/public-api.ts deleted file mode 100644 index 8e9058eaa1d7..000000000000 --- a/src/google-maps/google-map/public-api.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -export * from './google-map-module'; -export * from './google-map'; diff --git a/src/google-maps/google-map/tsconfig-build.json b/src/google-maps/google-map/tsconfig-build.json deleted file mode 100644 index 5204b9ba30de..000000000000 --- a/src/google-maps/google-map/tsconfig-build.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "../tsconfig-build", - "files": [ - "public-api.ts", - "../typings.d.ts" - ], - "angularCompilerOptions": { - "annotateForClosureCompiler": true, - "strictMetadataEmit": true, - "flatModuleOutFile": "index.js", - "flatModuleId": "@angular/google-maps/google-map", - "skipTemplateCodegen": true, - "fullTemplateTypeCheck": true - } -} diff --git a/src/google-maps/google-maps-module.ts b/src/google-maps/google-maps-module.ts new file mode 100644 index 000000000000..13fb213c63d0 --- /dev/null +++ b/src/google-maps/google-maps-module.ts @@ -0,0 +1,20 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {NgModule} from '@angular/core'; + +import {MapMarker, MapMarkerModule} from './map-marker/index'; + +import {GoogleMap, GoogleMapModule} from './google-map/index'; + +@NgModule({ + imports: [GoogleMapModule, MapMarkerModule,], + exports: [GoogleMap, MapMarker,], +}) +export class GoogleMapsModule { +} diff --git a/src/google-maps/index.ts b/src/google-maps/index.ts index 676ca90f1ffa..377088a75a70 100644 --- a/src/google-maps/index.ts +++ b/src/google-maps/index.ts @@ -6,4 +6,4 @@ * found in the LICENSE file at https://angular.io/license */ -export * from './public-api'; +export * from './google-maps-module'; diff --git a/src/google-maps/public-api.ts b/src/google-maps/public-api.ts index 9d11682064d7..bd57b5427d97 100644 --- a/src/google-maps/public-api.ts +++ b/src/google-maps/public-api.ts @@ -6,4 +6,6 @@ * found in the LICENSE file at https://angular.io/license */ -export * from '@angular/google-maps/google-map'; +export {GoogleMap} from './google-map/index'; +export {MapMarker} from './map-marker/index'; +export * from './google-maps-module'; diff --git a/src/google-maps/tsconfig-build.json b/src/google-maps/tsconfig-build.json index 7b8486eb9abc..df3b99e4eef7 100644 --- a/src/google-maps/tsconfig-build.json +++ b/src/google-maps/tsconfig-build.json @@ -12,9 +12,6 @@ ".", "../../dist/packages/google-maps" ], - "paths": { - "@angular/google-maps/*": ["../../dist/packages/google-maps/*"] - }, "types": [ "googlemaps" ] diff --git a/src/google-maps/tsconfig-tests.json b/src/google-maps/tsconfig-tests.json index 713d01322f47..0f0829b28ac1 100644 --- a/src/google-maps/tsconfig-tests.json +++ b/src/google-maps/tsconfig-tests.json @@ -11,9 +11,6 @@ "jasmine", "googlemaps" ], - "paths": { - "@angular/google-maps/*": ["./*"] - } }, "angularCompilerOptions": { "strictMetadataEmit": true, diff --git a/src/google-maps/tsconfig.json b/src/google-maps/tsconfig.json index b654928fc517..31ad9496d92f 100644 --- a/src/google-maps/tsconfig.json +++ b/src/google-maps/tsconfig.json @@ -4,9 +4,7 @@ "compilerOptions": { "rootDir": "..", "baseUrl": ".", - "paths": { - "@angular/google-maps": ["./*"] - }, + "paths": {}, "types": [ "jasmine", "googlemaps" From c574a1011134bf8af4b6b379486ac7b03077c8cf Mon Sep 17 00:00:00 2001 From: Matthew Ehrlich Date: Fri, 6 Sep 2019 14:38:26 -0700 Subject: [PATCH 8/9] feat(google-maps): Add map-marker component Fix formatting on google maps module. --- src/google-maps/google-maps-module.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/google-maps/google-maps-module.ts b/src/google-maps/google-maps-module.ts index 13fb213c63d0..d816f00546ad 100644 --- a/src/google-maps/google-maps-module.ts +++ b/src/google-maps/google-maps-module.ts @@ -9,12 +9,17 @@ import {NgModule} from '@angular/core'; import {MapMarker, MapMarkerModule} from './map-marker/index'; - import {GoogleMap, GoogleMapModule} from './google-map/index'; @NgModule({ - imports: [GoogleMapModule, MapMarkerModule,], - exports: [GoogleMap, MapMarker,], + imports: [ + GoogleMapModule, + MapMarkerModule, + ], + exports: [ + GoogleMap, + MapMarker, + ], }) export class GoogleMapsModule { } From 8a8e70efcd53f13808c983dfa32c85899ade0e75 Mon Sep 17 00:00:00 2001 From: Matthew Ehrlich Date: Fri, 6 Sep 2019 16:19:05 -0700 Subject: [PATCH 9/9] feat(google-maps): Add map-marker component. Add GoogleMap and MapMarker components to index for the google maps module. --- src/google-maps/BUILD.bazel | 1 - src/google-maps/index.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/google-maps/BUILD.bazel b/src/google-maps/BUILD.bazel index 9887c83162a0..c6ffa7c4762d 100644 --- a/src/google-maps/BUILD.bazel +++ b/src/google-maps/BUILD.bazel @@ -3,7 +3,6 @@ package(default_visibility = ["//visibility:public"]) load("//:packages.bzl", "ROLLUP_GLOBALS") load("//tools:defaults.bzl", "ng_module", "ng_package") -# Root "@angular/google-maps" entry-point that does not re-export individual entry-points. ng_module( name = "google-maps", srcs = glob( diff --git a/src/google-maps/index.ts b/src/google-maps/index.ts index 377088a75a70..676ca90f1ffa 100644 --- a/src/google-maps/index.ts +++ b/src/google-maps/index.ts @@ -6,4 +6,4 @@ * found in the LICENSE file at https://angular.io/license */ -export * from './google-maps-module'; +export * from './public-api';