Ionic3 / Angular4:双向数据绑定在Google Maps发生点击事件后停止工作 [英] Ionic3/Angular4: Two-way databinding stops working after click event on Google-Maps

查看:80
本文介绍了Ionic3 / Angular4:双向数据绑定在Google Maps发生点击事件后停止工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using Ionic 3 and I am using the Google Maps plugin for it. I have two pages, a list and a map. I display the same objects on both views and when you click a list entry or a marker (info window), the object's detail page will be opened where you can rate the selected object.

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

Anyway, when I open the detail page via the list, everything works fine but when I open the detail page via the map-marker, the two-way data binding stops working. In the code below you can find the <rating-input> component in the rating dialog. That's the code that's not working.

我尝试使用一个简单的输入文本来确定这是否真的是双向数据绑定还是它是我的组件。数据绑定也无法通过简单的文本框进行。

I've tried using a simple input text to find out if it's really the two way data binding or if it's my component. The data binding did not work either using the simple textbox.

以下是代码:

 //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

Rating-input component 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,Input,Output,EventEmitter};

import { Component, Input, Output, EventEmitter } from "@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);
  }
}


推荐答案

问题出在这里:

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

来自Google Maps api的click事件使用其自己的事件监听器,您必须收听他们使用 addListener 。问题是,它正在 ngZone 之外运行。要重新进入区域,在发生类似事件之后,您需要向组件中注入 ngZone 并执行 ngZone.run()

A click event coming from the google maps api uses its own event listeners, and you have to listen to them using addListener. The problem is, that this is running outside the ngZone. To re-enter the zone, after an event like that has occured, you need to inject ngZone into your component, and execute ngZone.run():

constructor(private readonly ngZone: NgZone) {}  

// ...
putMarkersForMarkets(): void {

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

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

This will make sure that any code running inside the run() method will be running inside the zone, and therefore will trigger the change detection

这篇关于Ionic3 / Angular4:双向数据绑定在Google Maps发生点击事件后停止工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆