2017-11-17 1 views
0

Ich verwende Ionic 3 und verwende das Google Maps-Plugin dafür. Ich habe zwei Seiten, eine Liste und eine Karte. Ich zeige dieselben Objekte in beiden Ansichten an und wenn Sie auf einen Listeneintrag oder eine Markierung (Informationsfenster) klicken, wird die Detailseite des Objekts geöffnet, in der Sie das ausgewählte Objekt bewerten können.Ionic3/Angular4: Zwei-Wege-Databinding funktioniert nicht mehr nach Klick-Ereignis auf Google-Maps

Wie auch immer, wenn ich die Detailseite über die Liste öffne, funktioniert alles gut, aber wenn ich die Detailseite über den Kartenmarker öffne, funktioniert die bidirektionale Datenbindung nicht mehr. Im folgenden Code finden Sie die Komponente <rating-input> im Bewertungsdialog. Das ist der Code, der nicht funktioniert.

Ich habe versucht, einen einfachen Eingabetext zu verwenden, um herauszufinden, ob es wirklich die Zwei-Wege-Datenbindung ist oder ob es meine Komponente ist. Die Datenbindung funktionierte nicht mit dem einfachen Textfeld. Hier

ist der Code:

//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 }); 
    } 

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

Rating Popup Typoskript:

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); 
    }); 

    } 

} 

Rating-Eingabekomponente 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> 

Rating-Eingabekomponente Maschinenschrift

import {Component, Eingabe, Ausgabe, EventEmitter} von "@ Winkel/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); 
    } 
} 

Antwort

1

Das Problem liegt hier:

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

Ein Klick Ereignis aus den Karten api google kommt seinen eigenen Event-Listener verwendet, und Sie müssen hören Sie sie mit addListener. Das Problem ist, dass dies außerhalb der ngZone läuft. Um wieder in die Zone, nachdem ein Ereignis wie das aufgetreten ist, müssen Sie ngZone in Ihrer Komponente injizieren, und führen ngZone.run():

constructor(private readonly ngZone: NgZone) {} 

// ... 
putMarkersForMarkets(): void { 

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

Dies wird sicherstellen, dass jeder Code innerhalb der run() Methode ausgeführt wird ausgeführt innerhalb der Zone, und wird daher die Änderungserkennung auslösen

+0

Ja, es funktioniert jetzt! Vielen Dank! –

-1

Sie können Ng Verwenden Zone

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();}); 
    } 
    } 
Verwandte Themen