Ionic3 / Angular4:双向数据绑定在Google-Maps

时间:2017-11-17 13:44:28

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

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

无论如何,当我通过列表打开详细页面时,一切正常,但是当我通过map-marker打开详细页面时,双向数据绑定停止工作。在下面的代码中,您可以在评级对话框中找到<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 });
   }

评级-Popup 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>

评级输入组件打字稿

从&#34; @ angular / core&#34;;

导入{Component,Input,Output,EventEmitter}
@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);
  }
}

2 个答案:

答案 0 :(得分:1)

问题在于:

StationId

来自google maps api的点击事件使用自己的事件侦听器,您必须使用.then(marker => { marker.on(GoogleMapsEvent.INFO_CLICK) .subscribe(() => { this.onClickMarket(market); }); }); 收听它们。问题是,这是在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)); }); }); } 方法内运行的任何代码都将在区域内运行,因此将触发更改检测

答案 1 :(得分:-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();});
    }
    }