【问题标题】:Ionic3/Angular4: Two-way databinding stops working after click event on Google-MapsIonic 3/Angular:谷歌地图上的点击事件后双向数据绑定停止工作
【发布时间】:2018-05-01 07:30:53
【问题描述】:

我正在使用 Ionic 3,并且我正在使用 Google Maps 插件。我有两个页面,一个列表和一个地图。我在两个视图上显示相同的对象,当您单击列表条目或标记(信息窗口)时,将打开对象的详细信息页面,您可以在其中对所选对象进行评分。

无论如何,当我通过列表打开详细信息页面时,一切正常,但是当我通过地图标记打开详细信息页面时,双向数据绑定停止工作。在下面的代码中,您可以在评级对话框中找到<rating-input> 组件。那是代码不起作用。

我尝试使用简单的输入文本来确定它是否真的是双向数据绑定,或者它是否是我的组件。使用简单的文本框,数据绑定也不起作用。

代码如下:

 //adding the markers to the map and adding the clicklisteners
 putMarkersForMarkets(markets: Christmasmarket[]) {


markets.forEach(market => {
  let isOpen = this.openinghoursService.isOpenAt(market, new Date());
  this.map.addMarker({
    title: market.name,
    icon: isOpen ? 'green' : 'red',
    animation: 'DROP',
    position: {
      lat: market.position.latitude,
      lng: market.position.longitude
    }
  }).then(marker => {
    marker.on(GoogleMapsEvent.INFO_CLICK)
      .subscribe(() => {
        this.onClickMarket(market);
      });
  });;

});


}

onClickMarket(market: Christmasmarket) {
       this.map.setVisible(false);
       this.map.setClickable(false);
     this.app.getRootNav().push(MarketDetailPage, { data: market });
   }

评分弹出 html:

<ion-header>
  <ion-navbar color="primary">
    <ion-title>{{'RATINGDIALOG.TITLE' | translate}}</ion-title>
    <ion-buttons end>
      <button ion-button icon-only (click)="dismiss()">
      <ion-icon name="close"></ion-icon>
    </button>
    </ion-buttons>
  </ion-navbar>
</ion-header>
<ion-content padding>
  <form #form="ngForm">
    <b>{{'RATINGDIALOG.HEADERMARKET' | translate}}</b><br>
    <rating-input [(rating)]="rating" [texts]="ratingTexts" name="rating"></rating-input>
    <b>{{'RATINGDIALOG.HEADERPRICE' | translate}}</b><br>
    <rating-input [(rating)]="ratingPrice" symbol="logo-euro" [texts]="ratingPriceTexts"></rating-input>

    <input type="text" [(value)]="meinval">

    {{meinval}}
  </form>
</ion-content>
<ion-footer>
  <ion-row>
    <ion-col>
      <button [disabled]="rating == 0 || ratingPrice == 0" ion-button full color="secondary" (click)="saveRating()">
        {{'RATINGDIALOG.SAVE' | translate}}
    </button>
    </ion-col>
    <ion-col>
      <button ion-button full color="secondary" (click)="dismiss()">{{'RATINGDIALOG.CANCEL' | translate}}
      </button>
    </ion-col>
  </ion-row>
</ion-footer>

评分弹出打字稿:

import { Component, OnInit } from '@angular/core';
import { ViewController, NavParams } from 'ionic-angular';
import { Christmasmarket } from "../../../model/christmasmarket";
import { ChristmasMarketService } from "../../../services/christmasmarketservice";
import { TranslateService } from "@ngx-translate/core";

@Component({
  selector: 'rating-dialog',
  templateUrl: 'ratingdialog.component.html'
})
export class RatingDialogComponent implements OnInit {


  rating: number;
  ratingPrice: number;

  ratingTexts: Array<string>;
  ratingPriceTexts: Array<string>;

  market: Christmasmarket;

  meinval: String;
  constructor(
    private viewCtrl: ViewController,
    private navParams: NavParams,
    private christmasMarketService: ChristmasMarketService,
    private translate: TranslateService
  ) {

  }

  ngOnInit(): void {

    this.translate.get('RATINGTEXTS').subscribe(res => {
      this.ratingTexts = [];
      this.ratingTexts.push(res['VALUE1']);
      this.ratingTexts.push(res['VALUE2']);
      this.ratingTexts.push(res['VALUE3']);
      this.ratingTexts.push(res['VALUE4']);
      this.ratingTexts.push(res['VALUE5']);
    });


    this.translate.get('RATINGPRICETEXTS').subscribe(res => {
      this.ratingPriceTexts = [];
      this.ratingPriceTexts.push(res['VALUE1']);
      this.ratingPriceTexts.push(res['VALUE2']);
      this.ratingPriceTexts.push(res['VALUE3']);
      this.ratingPriceTexts.push(res['VALUE4']);
      this.ratingPriceTexts.push(res['VALUE5']);
    });

    this.market = this.navParams.get('data');
    this.rating = 0;
    this.ratingPrice = 0;

    this.christmasMarketService.findRatingOfMarket(this.market.id).then(rating => {

      if (rating) {
        this.rating = rating.rating;
        this.ratingPrice = rating.ratingPrice;
      }
    }).catch(e => {

        console.log(e);
    });
  }

  dismiss() {
    this.viewCtrl.dismiss(this.market);
  }

  saveRating() {
    this.christmasMarketService.rateMarket(this.market.id, this.rating, this.ratingPrice).then(market => {
      this.market = market;
      this.dismiss();
      console.log(market);
  }).catch(e => {
      console.log(e);
  });

  }

}

评分输入组件html

<button ion-button icon-only clear="true" (click)="onClickRating(num)" *ngFor="let num of possibleRatings">
<ion-icon [name]="symbol"  [color]="rating >= num ? 'black' : 'grey'"></ion-icon>
</button>
<p *ngIf="texts">
    {{texts[rating-1]}}
</p>
<p *ngIf="!rating || rating == 0">
    -
</p>

评级输入组件打字稿

从“@angular/core”导入{组件、输入、输出、事件发射器};

@Component({
  selector: 'rating-input',
  templateUrl: 'ratinginput.component.html'
})
export class RatingInputComponent{

  @Input() @Output() rating: number;
  @Input() symbol: string = 'star';
  @Input() texts : Array<string>;

  @Output() ratingChange = new EventEmitter();

  possibleRatings: Array<number> = [1, 2, 3, 4, 5];

  onClickRating(rating: number) {
    this.rating = rating;
    this.ratingChange.emit(this.rating);
  }
}

【问题讨论】:

    标签: angular google-maps ionic-framework cordova-plugins


    【解决方案1】:

    你可以使用 Ng 区域

     import { NgZone  } from '@angular/core';
    
        export class AppComponent {
    
        constructor(public zone: NgZone){
         window['AppComponent'] = {component: this, zone: zone};
        }
        onClickRating(){
        window['AppComponent'].zone.run(() => {window['AppComponent'].component.yourFunctionName();});
        }
        }
    

    【讨论】:

      【解决方案2】:

      问题出在这里:

      .then(marker => {
          marker.on(GoogleMapsEvent.INFO_CLICK)
            .subscribe(() => {
              this.onClickMarket(market);
            });
      });
      

      来自 google maps api 的点击事件使用其自己的事件侦听器,您必须使用 addListener 来侦听它们。问题是,这是在ngZone 之外运行的。要重新进入该区域,在发生类似事件后,您需要将ngZone 注入到您的组件中,并执行ngZone.run()

      constructor(private readonly ngZone: NgZone) {}  
      
      // ...
      putMarkersForMarkets(): void {
      
          // ...
          .then(marker => {
              marker.on(GoogleMapsEvent.INFO_CLICK).subscribe(() => {
                  this.ngZone.run(() => this.onClickMarket(market));
              });
          });
      }
      

      这将确保在run() 方法内运行的任何代码都将在区域内运行,因此将触发更改检测

      【讨论】:

        猜你喜欢
        • 2017-06-20
        • 1970-01-01
        • 2017-04-27
        • 2015-09-12
        • 1970-01-01
        • 2016-03-05
        • 1970-01-01
        • 2020-12-20
        • 1970-01-01
        相关资源
        最近更新 更多