【问题标题】:Google Places Autocomplete + Angular2谷歌地方自动完成 + Angular2
【发布时间】:2017-07-09 13:50:51
【问题描述】:

我正在构建一个简单的 Google Places Autocomplete Angular2 指令,但问题是无法获得任何预测(响应始终为空?!)...

作为概念证明,我创建了最简单的代码 sn-p 作为参考:

<!DOCTYPE html>
<html>

<head>
    <script src="https://maps.googleapis.com/maps/api/js?key=[MY_API_KEY]&libraries=places" async defer></script>
</head>

<body>
    <button type="button" onclick="go()">go</button>
    <input id="autocomplete" type="text"></input>
    <script>
    var autocomplete = null;

    function go() {
        autocomplete = new google.maps.places.Autocomplete(
            (document.getElementById('autocomplete')), {
                types: ['geocode']
            });
    }
    </script>
</body>

</html>

上面的代码有效——点击Go按钮后我可以得到预测。

现在,Angular2 场景:

我的 _Layout.cshtml 文件在 head 部分有以下标签:

<script src="https://maps.googleapis.com/maps/api/js?key=[MY_API_KEY]&libraries=places" async defer></script>

我的指令:

从'@angular/core'导入{指令,ElementRef,输入}; 声明 var google: any; @Directive({ 选择器:'[googleplaces]' }) 导出类 GooglePlacesDirective { 自动完成:任何; 构造函数(私有 el:ElementRef){ } ngAfterContentInit() { this.autocomplete = 新的 google.maps.places.Autocomplete( (this.el.nativeElement), { 类型:['geocode', 'cities'] }); } }

还有简单的 Angular 组件:

<form [formGroup]="companyForm">
   
    .
    .
    .

    <div class="form-group">
        <label for="Location">Location</label>
        <input type="text" 
               class="form-control" 
               id="Location" 
               fromControlName="Location" 
               googleplaces>
    </div>
</form>

场景 2(角度)不起作用。事实:

  • 自动完成已初始化(它具有所有预期的属性/方法,占位符是“输入位置”等...)
  • 自动完成不会为键入的搜索字符串返回任何预测(它只返回“/**/xdc._le3zv3 && xdc._le3zv3( [4] )” )

另外,谷歌 API 控制台说一切都是应该的?!这是截图:

这里有什么问题?谢谢...

【问题讨论】:

    标签: angular google-places-api


    【解决方案1】:
    import {Directive, ElementRef, EventEmitter, Output} from '@angular/core';
    import {NgModel} from '@angular/forms';
    
    declare var google:any;
    
    @Directive({
      selector: '[Googleplace]',
      providers: [NgModel],
      host: {
        '(input)' : 'onInputChange()'
      }
    })
    export class GoogleplaceDirective {
    
       @Output() setAddress: EventEmitter<any> = new EventEmitter();
      modelValue:any;
      autocomplete:any;
      private _el:HTMLElement;
    
    
      constructor(el: ElementRef,private model:NgModel) {
        this._el = el.nativeElement;
        this.modelValue = this.model;
        var input = this._el;
    
        this.autocomplete = new google.maps.places.Autocomplete(input, {});
        google.maps.event.addListener(this.autocomplete, 'place_changed', ()=> {
          var place = this.autocomplete.getPlace();
          this.invokeEvent(place);
    
        });
      }
    
      invokeEvent(place:Object) {
        this.setAddress.emit(place);
      }
    
      onInputChange() {
        console.log(this.model);
      }
    }
    

    使用

    <input type="text" class="form-control" placeholder="Location" name="Location" [(ngModel)]="address" #LocationCtrl="ngModel"
            Googleplace (setAddress)="getAddressOnChange($event,LocationCtrl)">
    

    【讨论】:

    • 完美!非常感谢@Habeeb!
    • 如果你得到预期的结果。请标记为正确答案。 meta.stackexchange.com/questions/5234/…
    • 嗨 Habeeb,我是 Angular 2 的新手。我正在尝试在我的页面中添加一个自动完成功能...当我在搜索解决方案时,我发现了这篇文章。当“this.autocomplete =新的 google.maps.places.Autocomplete(input, {});"这条线到达我收到一个错误,如“InvalidValueError:不是 HTMLInputElement 的实例”..你能帮我找出这个错误吗???
    • @Girija 你是否在代码中添加了
    • 我必须将this.setAddress.emit(place); 的调用封装在构造函数中的NgZone.run(): constructor(private zone: NgZone, ..) 中,然后在事件侦听器中封装this.zone.run(() =&gt; {this.setAddress.emit(place);})。没有它,一些模型到 UI 视图同步不会立即触发
    【解决方案2】:

    @Habeeb 的回答是一个很好的开始,但这是一个更简洁的实现。首先安装 googlemaps typings npm install --save-dev @types/googlemaps 并将它们导入您的应用程序中的某个位置 import {} from '@types/googlemaps'

    import { Directive, ElementRef, EventEmitter, OnInit, Output } from '@angular/core';
    
    @Directive({
      // xx is your app's prefix
      selector: '[xxPlaceLookup]'
    })
    export class PlaceLookupDirective implements OnInit {
      @Output() onSelect: EventEmitter<any> = new EventEmitter();
    
      private element: HTMLInputElement;
    
      constructor(el: ElementRef) {
        this.element = el.nativeElement;
      }
    
      ngOnInit() {
        const autocomplete = new google.maps.places.Autocomplete(this.element, {
          types: ['establishment'],
          componentRestrictions: {country: 'us'}
        });
        google.maps.event.addListener(autocomplete, 'place_changed', () => {
          const place = autocomplete.getPlace();
          this.onSelect.emit(place);
        });
      }
    }
    

    【讨论】:

    • 更简洁的实现。
    • 我必须将this.setAddress.emit(place); 的调用封装在构造函数中的NgZone.run(): constructor(private zone: NgZone, ..) 中,然后在事件侦听器中封装this.zone.run(() =&gt; {this.setAddress.emit(place);})。没有它,一些模型到 UI 视图同步不会立即触发
    • 应用中的某个地方是什么意思?
    猜你喜欢
    • 1970-01-01
    • 2014-01-02
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多