离子输入值[(ngModel)]未通过相对组件成员变量更新得到更新

时间:2018-02-19 06:25:16

标签: javascript angular google-maps typescript ionic-framework

我是新手,并获得了Ionic框架的经验。虽然使用离子I进行编码但遇到了下面给出的一个问题

离子页面/模板代码

<ion-item>
  <ion-label floating>{{ addressLabel }}</ion-label>
  <ion-input name="address" id="addressField" type="text" required [(ngModel)]="address" #userAddress></ion-input>
</ion-item>
<div #locationMap id="locationMap"></div>

映射组件代码以更新标记丢弃时的地址值

onMarkerDrop(event) {
    let latcurr = event.latLng.lat();
    let longcurr = event.latLng.lng();
    this.initializeCurrent(latcurr, longcurr);
    let latLng = {lat: event.latLng.lat(), lng: event.latLng.lng()};
    let infoWindow = new google.maps.InfoWindow();
    infoWindow.open(this.map, this.marker);
    infoWindow.close();
  }

  initializeCurrent(latcurr, longcurr) {
    this.currgeocoder = new google.maps.Geocoder();
    if (latcurr != '' && longcurr != '') {
        let myLatlng = new google.maps.LatLng(latcurr, longcurr);
        this.currgeocoder.geocode({'location': myLatlng}, (results, status) => {
          if (status == google.maps.GeocoderStatus.OK) {
              this.address = results[0].formatted_address; 

// From above I am getting new location address on marker drop but that new address is not getting reflected at address input box.

              console.log(this.address);
              setTimeout(() => { 
                this.userAddress.setFocus();
                this.keyboard.close();
              }, 500);
          } else {
              alert('Geocode was not successful for the following reason: ' + status);
          }
      });
    }
  }

我没有得到我做错的事。请引导我通过正确的方式。谢谢。

1 个答案:

答案 0 :(得分:1)

这是因为address被传递给google.maps.Geocoder.prototype.geocode的回调函数修改。回调是由Angular区域的<{1>}方法外部异步调度的。

Angular 使用 zone.js (Angular团队的一个副项目)来确定跨函数调用的逻辑调用上下文,以便更有效地处理更改检测。通过跟踪当前geocode框架特定的异步编程抽象(仅由Angular使用),该框架减少了在95%快乐路径中重新渲染视图所需的次数。

在此上下文之外运行的代码不会触发视图的更新。

这是一种痛苦。

要解决此问题,您可能需要将代码包装在 Angular区域中。这将使更改检测在调用图中流动。

这是什么样的

zone

在遇到这种情况之后,人们常常开始将各种不相关的错误归因于区域内的问题,而这些问题实际上是无关的。

需要在上面创建显式区域的原因是框架与import {Component, NgZone} from '@angular/core'; @Component({ // boilerplate }) export default class MapComponent { constructor(readonly ngZone: NgZone) {} initializeCurrent(latcurr, longcurr) { if (!latcurr || !longcurr) { return; } this.currgeocoder = new google.maps.Geocoder(); const latlng = new google.maps.LatLng(latcurr, longcurr); this.currgeocoder.geocode({'location': latlng}, ([{formatted_address}], status) => { if (status === google.maps.GeocoderStatus.OK) { // Create a zone right here. this.ngZone.run(() => { // changes will be detected because we are in a zone. this.address = formatted_address; }); // The scope of a user-created zone should be as limited as possible. console.log(this.address); setTimeout(() => { this.userAddress.setFocus(); this.keyboard.close(); }, 500); } else { alert(`Geocode was not successful for the following reason: ${status}`); } }); } } 调用您提供的回调的机制或时间之间没有逻辑连接。

大多数情况下,在编写良好的应用程序中接近100%,该区域将自动且隐式地传播,因为您的异步代码应该在Promises或Observables中。这些是框架所知道的规范异步原语(它将它们修补为挂钩...)。在Angular应用程序中总有一个区域,但您通常不会关心。

当您知道需要区域时,请务必小心使用区域。

如果你开始迷信地使用它们,你的应用程序将会变慢,你将无法理解正在发生的事情,你的代码将大大降低质量,你会疯了。

保守。

<强>附录:

正如我所提到的,编写良好的应用程序通常不会使用显式区域,而是使用Promises等标准API和Observables等半标准API。

虽然我倾向于赞成Promises,或者至少感觉我喜欢Angular,因为大多数Angular Observable都应该是Promises(XHR任何人?),在这种情况下提高抽象级别的正确方法实际上是使用Observables

原因是多次调用回调。

因此,我们实际上可以重写此代码,通过调整geocode API来删除低级别且通常容易出错的区域使用。

以下是

geocode

令人瞩目的是代码变得多么简单。当observable用于表示信息的异步​​时,它们可以非常优雅。毕竟,他们的设计代表了什么。当它们用于表示单数,甚至可能是同步值或同步流时,阻抗不匹配的程度令人作呕。

框架设计师,甚至更多的规范推动者,应该倾听Rx的创建者Erik Meijer并使用正确的工具来做正确的工作,而不是通过推送他们(双关语)给Observables一个坏名字意图?)代表数字import {Component} from '@angular/core'; import Rx from 'rxjs'; @Component({ // boilerplate }) export default class MapComponent { initializeCurrent(latcurr, longcurr) { if (!latcurr || !longcurr) { return; } this.currgeocoder = new google.maps.Geocoder(); const latlng = new google.maps.LatLng(latcurr, longcurr); const addressObservable = new Rx.Observable(observer => { this.currgeocoder.geocode({'location': latlng}, ([{formatted_address}], status) => { observer.next({status, address: formatted_address}); }); }); addressObservable.do(() => { setTimeout(() => { this.userAddress.setFocus(); this.keyboard.close(); }, 500); }) .subscribe(({status, address})=> { if (status === google.maps.GeocoderStatus.OK) { this.address = address; } else { alert(`Geocode was not successful for the following reason: ${status}`) } }); } } 的任务。 现在他们故意无视他,并像Reactive Streams规范一样制造绝对的垃圾。

但是Observables在他们被设计为惊人的东西时非常惊人。

分手:

我说这一切都是因为我老实说他讨厌我刚写的Rx版本。

Angular,围绕Reactive Streams规范的可笑的炒作,以及提出将技术标准化为JavaScript的方式(即&#34;它必须允许同步观察,因为它必须能够替换所有库和控制结构&#34; ),让我讨厌Rx,让我不想用任何东西,这是一件令人伤心的事情。