Angular return 来自 google PlacesService 并添加到 Observable
Angular return results from google PlacesService and add to Observable
使用下面的方法我可以使用 placeId 成功检索地点详细信息。
getPlaceDetails(placeId) {
this.mapsAPILoader.load().then(() => {
const service = new google.maps.places.PlacesService($('#service-helper').get(0));
service.getDetails({'placeId': placeId}, (results, status) => {
if (status === google.maps.places.PlacesServiceStatus.OK) {
if (results) {
console.log(results);
}
}
});
});
}
我有另一种方法可用于从 Firebase (Firestore) 检索我的所有客户,我正在尝试通过传递每个 placeId 添加从 getPlaceDetails 收到的详细信息,但我不确定如何获取来自 getPlaceDetails 的结果,并在映射时将它们添加到每个安装程序。我的目标是让 getInstallers() 达到 return 类似 return {id, ...data, ...results} 任何帮助将不胜感激!
getInstallers(): Observable<Installer[]> {
const installersCollection = this.afs.collection<Installer>('installers');
return installersCollection.snapshotChanges().map(installers => {
return installers.map(i => {
const data = i.payload.doc.data() as Installer;
const id = i.payload.doc.id;
this.getPlaceDetails(data.placeId);
return { id, ...data };
});
});
}
这是 stackblitz 上的一个非常简化的版本:https://stackblitz.com/edit/angular-23mu7g
嘿,这是一个可行的解决方案:
当你需要直接与DOM交互时请使用angular方式,不推荐使用此行(使用Jquery):
const service = new google.maps.places.PlacesService($('#service-helper').get(0));
Angular方式:
@ViewChild('serviceHelper') serviceHelper;
并且由于您正在更改分页器和排序指令的值,您可能会收到此错误:ExpressionChangedAfterItHasBeenCheckedError
您应该触发 detecChanges()
方法但首先导入 changeDetectorRef
:
import { ..., ChangeDetectorRef } from '@angular/core';
this.ref.detectChanges();
请记住,当您直接引用 DOM 中的元素时(使用 @ViewChild
装饰器),在执行 ngAfterViewInit
之前它们并不完全可靠. app.component.ts
import {Component, ViewChild, ChangeDetectorRef } from '@angular/core';
...
@ViewChild('serviceHelper') serviceHelper;
...
constructor(private mapsAPILoader: MapsAPILoader, private ref: ChangeDetectorRef) {}
ngAfterViewInit() {
// Create 100 users
const businesses = [
{placeId: 'ChIJHWJmnEbxxokRxI5WpqIW9jo'},
{placeId: 'ChIJeUdT2ikPK4cRpqJK61nKvuk'},
{placeId: 'ChIJ24q4qLMsDogRkwzJD2maZcw'},
];
const updatedBusinesses = []
businesses.forEach(business => {
this.getPlaceDetails(business.placeId)
.subscribe(place => {
console.log(place);
updatedBusinesses.push({
placeId: business.placeId,
name: place.name,
rating: place.rating
});
// Assign the data to the data source for the table to render
this.dataSource = new MatTableDataSource(updatedBusinesses);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.ref.detectChanges();
});
})
}
...
getPlaceDetails(placeId): Observable<any> {
const callback = (results, status) => {
if (status === google.maps.places.PlacesServiceStatus.OK) {
if (results) {
return results;
}
}
};
return this.loadMapsApi().pipe(concatMap(place => {
const service = new google.maps.places.PlacesService(this.serviceHelper.nativeElement);
let $getDetailsAsObservable : any;
$getDetailsAsObservable = bindCallback(service.getDetails.bind(service), callback);
return $getDetailsAsObservable({'placeId': placeId});
}));
}
loadMapsApi(): Observable<any> {
const $mapsAPILoader = fromPromise(this.mapsAPILoader.load());
return $mapsAPILoader;
}
app.component.html
...
<div id="service-helper" #serviceHelper></div>
...
使用下面的方法我可以使用 placeId 成功检索地点详细信息。
getPlaceDetails(placeId) {
this.mapsAPILoader.load().then(() => {
const service = new google.maps.places.PlacesService($('#service-helper').get(0));
service.getDetails({'placeId': placeId}, (results, status) => {
if (status === google.maps.places.PlacesServiceStatus.OK) {
if (results) {
console.log(results);
}
}
});
});
}
我有另一种方法可用于从 Firebase (Firestore) 检索我的所有客户,我正在尝试通过传递每个 placeId 添加从 getPlaceDetails 收到的详细信息,但我不确定如何获取来自 getPlaceDetails 的结果,并在映射时将它们添加到每个安装程序。我的目标是让 getInstallers() 达到 return 类似 return {id, ...data, ...results} 任何帮助将不胜感激!
getInstallers(): Observable<Installer[]> {
const installersCollection = this.afs.collection<Installer>('installers');
return installersCollection.snapshotChanges().map(installers => {
return installers.map(i => {
const data = i.payload.doc.data() as Installer;
const id = i.payload.doc.id;
this.getPlaceDetails(data.placeId);
return { id, ...data };
});
});
}
这是 stackblitz 上的一个非常简化的版本:https://stackblitz.com/edit/angular-23mu7g
嘿,这是一个可行的解决方案:
当你需要直接与DOM交互时请使用angular方式,不推荐使用此行(使用Jquery):
const service = new google.maps.places.PlacesService($('#service-helper').get(0));
Angular方式:
@ViewChild('serviceHelper') serviceHelper;
并且由于您正在更改分页器和排序指令的值,您可能会收到此错误:ExpressionChangedAfterItHasBeenCheckedError
您应该触发 detecChanges()
方法但首先导入 changeDetectorRef
:
import { ..., ChangeDetectorRef } from '@angular/core';
this.ref.detectChanges();
请记住,当您直接引用 DOM 中的元素时(使用 @ViewChild
装饰器),在执行 ngAfterViewInit
之前它们并不完全可靠. app.component.ts
import {Component, ViewChild, ChangeDetectorRef } from '@angular/core';
...
@ViewChild('serviceHelper') serviceHelper;
...
constructor(private mapsAPILoader: MapsAPILoader, private ref: ChangeDetectorRef) {}
ngAfterViewInit() {
// Create 100 users
const businesses = [
{placeId: 'ChIJHWJmnEbxxokRxI5WpqIW9jo'},
{placeId: 'ChIJeUdT2ikPK4cRpqJK61nKvuk'},
{placeId: 'ChIJ24q4qLMsDogRkwzJD2maZcw'},
];
const updatedBusinesses = []
businesses.forEach(business => {
this.getPlaceDetails(business.placeId)
.subscribe(place => {
console.log(place);
updatedBusinesses.push({
placeId: business.placeId,
name: place.name,
rating: place.rating
});
// Assign the data to the data source for the table to render
this.dataSource = new MatTableDataSource(updatedBusinesses);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.ref.detectChanges();
});
})
}
...
getPlaceDetails(placeId): Observable<any> {
const callback = (results, status) => {
if (status === google.maps.places.PlacesServiceStatus.OK) {
if (results) {
return results;
}
}
};
return this.loadMapsApi().pipe(concatMap(place => {
const service = new google.maps.places.PlacesService(this.serviceHelper.nativeElement);
let $getDetailsAsObservable : any;
$getDetailsAsObservable = bindCallback(service.getDetails.bind(service), callback);
return $getDetailsAsObservable({'placeId': placeId});
}));
}
loadMapsApi(): Observable<any> {
const $mapsAPILoader = fromPromise(this.mapsAPILoader.load());
return $mapsAPILoader;
}
app.component.html
...
<div id="service-helper" #serviceHelper></div>
...