2016-10-03 54 views
0

谷歌的地方我嘗試使用Google Places與觀測量的角度2.與觀測量的Angular2

爲了做到這一點,我包括谷歌的腳本在的index.html,然後我得到http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html一些靈感與觀測量

<!-- Script included in index.html --> 
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"></script> 

你可以看到整個應用程序有:https://embed.plnkr.co/LQaag2/

我認爲這是與事件的問題。例如,當用戶鍵入「P」時,不顯示任何內容。但是,如果他點擊頁面或鍵入「a」,則他將看到以「P」開頭的地點的結果。

你知道爲什麼嗎?


應用程序/ main.ts

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 
import { AppModule } from './app.module'; 
import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/debounceTime'; 
import 'rxjs/add/operator/distinctUntilChanged'; 
import 'rxjs/add/operator/switchMap' 

platformBrowserDynamic().bootstrapModule(AppModule); 

應用程序/ app.module.ts

import { NgModule } from '@angular/core'; 
import { BrowserModule } from '@angular/platform-browser'; 
import { JsonpModule } from '@angular/http'; 
import { ReactiveFormsModule } from '@angular/forms'; 
import { AppComponent } from './app.component'; 
import { GoogleSearchComponent } from './google-search.component' 
import { GoogleService } from './google.service'; 

@NgModule({ 
    imports: [BrowserModule, JsonpModule, ReactiveFormsModule], 
    declarations: [AppComponent, GoogleSearchComponent], 
    providers: [GoogleService], 
    bootstrap: [AppComponent] 
}) 
export class AppModule {} 

應用程序/ app.component.ts

import { Component } from '@angular/core'; 

@Component({ 
    selector: 'my-app', 
    templateUrl: 'app/app.component.html' 
}) 
export class AppComponent { } 

應用程序/應用程序.component.html

<google-search></google-search> 

應用程序/谷歌place.ts

export class GooglePlace { 
    constructor(public id: string, 
       public description: string 
) {} 
} 

應用程序/谷歌search.component.ts

import { Component } from '@angular/core'; 
import { FormControl } from '@angular/forms'; 
import { GoogleService } from './google.service'; 
import { GooglePlace } from './google-place'; 

@Component({ 
    selector: 'google-search', 
    template: ` 
    <div> 
     <h2>Google Search</h2> 
     <input type="text" [formControl]="term"> 
     <ul> 
     <li *ngFor="let item of items | async">{{item.description}}</li> 
     </ul> 
    </div> 
    ` 
}) 
export class GoogleSearchComponent { 

    items: Observable<Array<GooglePlace>>; 
    term = new FormControl(); 

    constructor(private googleService: GoogleService) {} 

    ngOnInit() { 
    this.items = this.term.valueChanges 
       .debounceTime(400) 
       .distinctUntilChanged() 
       .switchMap(term => this.googleService.search(term)); 
    } 
} 

應用程序/ google.service.ts

import { Injectable } from '@angular/core'; 
import { GooglePlace } from './google-place'; 
import { Observable } from 'rxjs/Observable'; 

declare var google: any; 

@Injectable() 
export class GoogleService {  
    search(term: string) { 
    return new Observable<GooglePlace[]>(observer => { 
     let result: GooglePlace[] = []; 
     let displaySuggestions = function(predictions: any, status: string) { 
     if (status != google.maps.places.PlacesServiceStatus.OK) { 
      alert(status); 
      return; 
     } 
     predictions.forEach(function(prediction: any) { 
      result.push(new GooglePlace(prediction.place_id, prediction.description)); 
     }); 
     observer.next(result); 
     observer.complete(); 
     }; 
     if (term) { 
     let service = new google.maps.places.AutocompleteService(); 
     service.getQueryPredictions({ input: term }, displaySuggestions); 
     } 
    }); 
    } 
} 

回答

0

我發現一個可怕的解決方案。在應用程序/谷歌search.component.ts,我已經添加了以下功能:

recursiveTimeout(ms: number = 1000): void { 
    setTimeout(() => { 
    this.recursiveTimeout(ms); 
    }, ms); 
} 

然後在ngOnInit功能,我稱之爲recursiveTimeout

ngOnInit(): void { 
    this.recursiveTimeout(); 
    // ... 
} 

通過這個解決方案,當用戶類型 「P」(例如):

  1. 結果將在谷歌API被擷取
  2. 結果將顯示在事件recursiveTimeout被觸發(最大1000毫秒)剛過

我願意接受任何更好的解決方案;)

1

,如果你仍然有興趣,但我不知道今天面對同樣的問題與引導式前進。我想我找到了一個解決方案,雖然我不認爲這是應該這樣做的方式。 無論如何,我的方法是收集數據並讓數據顯示爲靜態。

ngOnInit(): void { 
//this.recursiveTimeout(); 
this.items = this.searchTermStream 
    .debounceTime(300) 
    .distinctUntilChanged() 
    .switchMap((term: string) => this.placesService.search(term)) 

    .catch(() => { 
     this.searchFailed = true; 
     return Observable.of([]) 
    } 
) 
this.items.subscribe(res => { 
    this.places = res; 
    //places is a string array and stores all found places , in your case it 
    would be an array of GooglePlace 

    console.log(this.places); 
}); 
} 

然後你就可以在數據可用時立即訪問數據。

0

我剛剛有一個谷歌地圖非常類似的問題。我將在這裏分享我的回答,儘管這麼晚了。

問題是因爲谷歌地圖getQueryPredictions的回調函數displaySuggestions被稱爲「角度區域」之外,所以角度無法正確檢測其內部的更改。

解決方案相對簡單。只需對app/google.service.ts進行4個小改動即可。查看評論。

// import NgZone 
import { Injectable, NgZone } from '@angular/core'; 
import { GooglePlace } from './google-place'; 
import { Observable } from 'rxjs/Observable'; 

declare var google: any; 

@Injectable() 
export class GoogleService { 
    // Inject NgZone in the constructor 
    constructor(private _ngZone: NgZone) {} 
    search(term: string) { 
    // save 'this' to a constant or alternatively bind it to the callback function 
    const self = this; 
    return new Observable<GooglePlace[]>(observer => { 
     const result: GooglePlace[] = []; 
     const displaySuggestions = function(predictions: any, status: string) { 
     if (status !== google.maps.places.PlacesServiceStatus.OK) { 
      console.log('GoogleService search: ', status); 
      return; 
     } 
     // Wrap the prediction in the zone 
     self._ngZone.run(function() { 
      predictions.forEach(function(prediction: any) { 
      result.push(
       new GooglePlace(prediction.place_id, prediction.description) 
      ); 
      }); 
      observer.next(result); 
      observer.complete(); 
     }); 

     }; 
     if (term) { 
     const service = new google.maps.places.AutocompleteService(); 
     service.getQueryPredictions({ input: term }, displaySuggestions); 
     } 
    }); 
    } 
} 

編輯:也許你應該拿出從plunker您的API密鑰,但我想,這可能不是一個嚴重的問題,如果它是免費的,是專門爲的目的例子...