简体   繁体   English

Angular2双向绑定在谷歌地图回调后停止工作

[英]Angular2 two-way binding stop work after google maps callback

I work on an angular 2 application. 我正在进行角度2应用。 I have a google maps in it, with autocomplete. 我有一个谷歌地图,自动完成。 I have an input (with google autocomplete), and a search button. 我有一个输入(使用谷歌自动完成)和一个搜索按钮。 When i hit the search button, I send the input data to google geocode, and put a marker on the map. 当我点击搜索按钮时,我将输入数据发送到谷歌地理编码,并在地图上放置一个标记。 It's sounds simple, but after this, the angular2 data bindig just stop working. 这听起来很简单,但在此之后,angular2数据绑定才停止工作。 The input don't get the formatted address, the addressIsValid dont turn on true. 输入没有得到格式化的地址,addressIsValid没有打开true。

HTML: HTML:

<div class="input-group">
<input autocorrect="off" autocapitalize="off" spellcheck="off" type="text"
       class="form-control" [(ngModel)]="addressInput" #search id="address" (keydown)="addressChanged()">
<div class="input-group-btn">
    <button id="addressSubmitButton" type="submit" class="btn btn-default" [class.btn-success]="addressIsValid"
            (click)="submited(search.value)">
        {{ (addressIsValid ? 'addressInput.success' : 'addressInput.search') | translate }}
    </button>
</div>

Code: 码:

export class AddressInputComponent implements OnInit {
public map: google.maps.Map;
public autocomplete: google.maps.places.Autocomplete;
private geocoder: google.maps.Geocoder = new google.maps.Geocoder();
public marker: google.maps.Marker;
public defaultZoom: number;
public defaultLat: number;
public defaultLng: number;
public errorCode: number;
private addressIsValid: boolean;
@Input('address') private addressInput: string;
@Output() addressUpdated: EventEmitter<string> = new EventEmitter();

@ViewChild("search")
public searchElementRef: ElementRef;

constructor() {
    this.addressIsValid = false;
}

ngOnInit() {
    this.defaultZoom = 7;
    this.defaultLat = 47.338941;
    this.defaultLng = 19.396167;
    this.errorCode = null;

    this.autocomplete = new google.maps.places.Autocomplete(this.searchElementRef.nativeElement, {
        types: ["address"]
    });

    this._setMapToDefault();

    this.autocomplete.bindTo('bounds', this.map);

    this.autocomplete.addListener('place_changed', () => {
        this.addressInput = this.autocomplete.getPlace().formatted_address;
    })
}

private _setMapToDefault() {
    this.map = new google.maps.Map(document.getElementById('map'), {
        center: {lat: this.defaultLat, lng: this.defaultLng},
        zoom: this.defaultZoom,
        scrollwheel: false,
    });

    this.marker = new google.maps.Marker();
    this.marker.setMap(this.map);
}

submited() {
    this.geocoder.geocode( { 'address': this.addressInput}, (results, status) => {
        if (status == google.maps.GeocoderStatus.OK) {
            setInterval(this._changeInput(results[0]), 200);
        } else {
            this.addressIsValid = false;
            this.errorCode = 1;
            this._setMapToDefault();
        }
    });
}

private _changeInput(result) {
    this.errorCode = null;

    if (result.address_components[0].types[0] != "street_number") {
        this.addressIsValid = false;
        this.errorCode = 2;
        this._setMapToDefault();
        return;
    }

    // jQuery('#address').val(result.formatted_address);
    this.addressInput = result.formatted_address;
    this.addressUpdated.emit(this.addressInput);
    this.addressIsValid = true;

    this.map.setCenter(result.geometry.location);
    this.map.setZoom(17);
    this.marker.setPosition(result.geometry.location);
    this.marker.setVisible(true);
}

private addressChanged() {
    if (this.addressIsValid == true) {
        this.addressIsValid = false;
        this._setMapToDefault();
    }
}

} }

Change detection is not triggered because google.maps uses its own sets of events/addListener calls. 由于google.maps使用自己的事件/ addListener调用集,因此不会触发更改检测。 These events are -not- so called monkey patched by zone.js and therefor do not run in the Angular zone, which logically will not trigger a change detection cycle. 这些事件不会被zone.js称为猴子修补,因此不会在Angular区域中运行,这在逻辑上不会触发更改检测周期。

So you can solve this by injecting the ngZone service in your component, on which you can reenter the angular zone using the run method: 因此,您可以通过在组件中注入ngZone服务来解决此问题,您可以使用run方法重新进入角度区域:

constructor(private ngZone: NgZone) {}

ngOnInit() {
    //...
    this.autocomplete.addListener('place_changed', () => {
        this.ngZone.run(() => {
            this.addressInput = this.autocomplete.getPlace().formatted_address;
        });  
    })
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM