【问题标题】:Problems with Events in Angular2 and IonicAngular2 和 Ionic 中的事件问题
【发布时间】:2018-05-05 08:38:54
【问题描述】:

我在我的应用程序中设置了一个计时器组件,它基本上是一个倒计时计时器。当它完成倒计时时,我希望将两个不同的事件发送到两个不同的页面(ListItemDetails)。
ItemDetails 页面是我显示所选订单项目的页面,如果我在某个订单的ItemsDetail 页面并且计时器用完它应该执行一些逻辑。
问题是这只适用于List 页面中的最后一项(包含订单),我需要它来处理List 页面中的所有订单

--编辑--
我不会假装同时打开 2 个页面。问题是该事件应该为List 页面中的每个订单“启动”,但它却为最后一个订单执行此操作。

timer.ts

timerTick() {
  setTimeout(() => {
    if (!this.timer.runTimer) { return; }
    this.timer.timeRemaining--;
    this.timer.displayTime = this.getSecondsAsDigitalClock(this.timer.timeRemaining);
    if (this.timer.timeRemaining > 0) {
      this.timerTick();
    }
    else {
      this.timer.hasFinished = true;
      this.events.publish('timer:finished',this.timer.hasFinished,this.order);
      this.events.publish('timer:popnav'+this.order,this.timer.hasFinished,this.order)
    }
  }, 1000);
}

list.ts

constructor(private navCtrl: NavController,
            private navParams: NavParams,
            private events : Events) {
  this.events.subscribe("timer:finished", (value,id) => {
    ...
  })
}

itemTapped(event, sector,user) {
  this.navCtrl.push(ItemDetailsPage, { sector: sector, user: user });
}

list.html

<div *ngFor="let sector of order.sectors">
   <button ion-item detail-none class='col last-item' [disabled]="sector.timeOut" (click)="itemTapped($event,sector,order.user)">
     <ion-row>
       <ion-col col-3>
         <div class='timer-line'>
           <timer [timeInSeconds]="timeInSeconds(sector)" [order]="sector.orderId"></timer>
         </div>
       </ion-col>
       <ion-col class='pull-right'>
         {{ sector.name }} <i class="material-icons">arrow_forward</i>
       </ion-col>
     </ion-row>
   </button>
</div>

item-details.ts

constructor(private navCtrl: NavController,
            public navParams: NavParams, 
            public events: Events) {
  this.selectedOrder = navParams.get('sector');
  this.events.subscribe("timer:popnav"+this.selectedOrder.orderId,(value,id) => {
    ...
  });
}

ionViewWillLeave(){
  this.events.unsubscribe("timer:popnav"+this.selectedOrder.orderId);
}

【问题讨论】:

  • 我不明白你怎么能同时有 2 页“活着”。看了你的帖子好几遍了,还是没看懂你的问题。你能解释一下吗?
  • 我觉得他不是那个意思
  • @Proustibat 我编辑了问题,希望现在更清楚
  • @fabricio 我不是那个意思

标签: angular events ionic2 ionic3


【解决方案1】:

好的,我想我明白你的问题了 :-)

我试图重写一个例子来解决同样的问题。

如果问题是您希望接收在详细信息页面上完成的每个计时器的事件,您必须订阅 "timer:popnav" 而不是 "timer:popnav"+this.selectedOrder.orderId 并且对于您的计时器中的发布也是如此:this.events.publish('timer:popnav',this.timer.hasFinished,this.order) 而不是this.events.publish('timer:popnav'+this.order,this.timer.hasFinished,this.order)

事件在我的应用程序上运行良好,你可以在这里查看我为你推送的源代码:https://github.com/proustibat/timer-angular-ionic-issue

希望对你有帮助。

我在这里总结一下主要文件:

List.ts:

import {Component} from '@angular/core';
import {Events, NavController, NavParams} from 'ionic-angular';
import {ItemDetailsPage} from "../item-details/item-details";

@Component({
    selector: 'page-list',
    templateUrl: 'list.html',
})
export class ListPage {

    order = {
        user: "username",
        sectors: [{
            name: "First Sector",
            timeOut: false,
            orderId: 1
        },{
            name: "Second Sector",
            timeOut: false,
            orderId: 2
        },{
            name: "Third Sector",
            timeOut: false,
            orderId: 3
        }]
    };

    constructor(public navCtrl: NavController, public navParams: NavParams, private events : Events) {
        this.events.subscribe("timer:finished", ( value, id ) => {
            console.log("ListPage Event [timer:finished]: ", value, id);
        });
    }

    itemTapped(event, sector,user) {
        this.navCtrl.push(ItemDetailsPage, { sector: sector, user: user });
    }
}

List.html

<ion-header>
    <ion-navbar>
        <ion-title>List</ion-title>
    </ion-navbar>
</ion-header>

<ion-content padding>
    <ion-card *ngFor="let sector of order.sectors">
        <ion-card-header>
            <ion-card-title>{{ sector.name }}</ion-card-title>
        </ion-card-header>

        <ion-card-content>
            <button ion-button detail-none [disabled]="sector.timeOut" (click)="itemTapped($event, sector, order.user)">
                Open details
            </button>
            <timer [timeInSeconds]="5" [order]="sector.orderId"></timer>
        </ion-card-content>
    </ion-card>
</ion-content>

item-details.ts

import { Component } from '@angular/core';
import {Events, NavController, NavParams} from 'ionic-angular';

@Component({
    selector: 'page-item-details',
    templateUrl: 'item-details.html',
})
export class ItemDetailsPage {

    selectedOrder:any;
    eventsReceived:Array<any> = [];

    constructor(private navCtrl: NavController, public navParams: NavParams, public events: Events) {
        this.selectedOrder = navParams.get('sector');
        // this.events.subscribe("timer:popnav"+this.selectedOrder.orderId,(value,id) => {
        this.events.subscribe("timer:popnav",(value,id) => {
            console.log("ItemDetailsPage Event [timer:popnav]: ", value, id);
            this.eventsReceived.push({
                value,
                id
            });
        });
    }

    ionViewWillLeave(){
        // this.events.unsubscribe("timer:popnav"+this.selectedOrder.orderId);
        this.events.unsubscribe("timer:popnav");
    }

}

item-details.html

    <ion-navbar>
        <ion-title>Item Details</ion-title>
    </ion-navbar>

</ion-header>



<ion-content padding>


    <ion-card>
        <ion-card-header>
            <ion-card-title>Selected Order</ion-card-title>
        </ion-card-header>
        <ion-card-content>
            <ion-item>
                name: {{selectedOrder.name}}
            </ion-item>
            <ion-item>
                timeOut: {{selectedOrder.timeOut}}
            </ion-item>
            <ion-item>
                orderId: {{selectedOrder.orderId}}
            </ion-item>
        </ion-card-content>
    </ion-card>

    <ion-card *ngFor="let event of eventsReceived">
        <ion-card-header>
            <ion-card-title>Event received</ion-card-title>
        </ion-card-header>
        <ion-card-content>
            <ion-item>
                Event id: {{event.id}}
            </ion-item>
            <ion-item>
                Event value: {{event.value}}
            </ion-item>
        </ion-card-content>
    </ion-card>
</ion-content>

然后是你的计时器组件:

timer.ts

import {Component, EventEmitter, Input} from '@angular/core';
import {Events} from "ionic-angular";

export interface ITimer {
    seconds: number;
    secondsRemaining: number;
    runTimer: boolean;
    hasStarted: boolean;
    hasFinished: boolean;
    displayTime: string;
}

@Component({
    selector: 'timer',
    templateUrl: 'timer.html'
})
export class TimerComponent {

    @Input() timeInSeconds: number;
    @Input() order: any;
    public timer: ITimer;

    constructor(private events:Events) {
        console.log('Hello TimerComponent Component');
    }

    ngOnInit() {
        this.initTimer();
    }

    hasFinished() {
        return this.timer.hasFinished;
    }

    initTimer() {
        console.log("Timer.initTimer: order = ", this.order);
        if(!this.timeInSeconds) { this.timeInSeconds = 0; }

        this.timer = <ITimer>{
            seconds: this.timeInSeconds,
            runTimer: false,
            hasStarted: false,
            hasFinished: false,
            secondsRemaining: this.timeInSeconds
        };

        this.timer.displayTime = this.getSecondsAsDigitalClock(this.timer.secondsRemaining);
    }

    startTimer() {
        this.timer.hasStarted = true;
        this.timer.runTimer = true;
        this.timerTick();
    }

    pauseTimer() {
        this.timer.runTimer = false;
    }

    resumeTimer() {
        this.startTimer();
    }

    timerTick() {
        setTimeout(() => {
            if (!this.timer.runTimer) { return; }
            this.timer.secondsRemaining--;
            this.timer.displayTime = this.getSecondsAsDigitalClock(this.timer.secondsRemaining);
            if (this.timer.secondsRemaining > 0) {
                this.timerTick();
            }
            else {
                this.timer.hasFinished = true;
                this.events.publish('timer:finished',this.timer.hasFinished,this.order);
                // this.events.publish('timer:popnav'+this.order,this.timer.hasFinished,this.order);
                this.events.publish('timer:popnav',this.timer.hasFinished,this.order);
            }
        }, 1000);
    }



    getSecondsAsDigitalClock(inputSeconds: number) {
        var sec_num = parseInt(inputSeconds.toString(), 10); // don't forget the second param
        var hours   = Math.floor(sec_num / 3600);
        var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
        var seconds = sec_num - (hours * 3600) - (minutes * 60);
        var hoursString = '';
        var minutesString = '';
        var secondsString = '';
        hoursString = (hours < 10) ? "0" + hours : hours.toString();
        minutesString = (minutes < 10) ? "0" + minutes : minutes.toString();
        secondsString = (seconds < 10) ? "0" + seconds : seconds.toString();
        return hoursString + ':' + minutesString + ':' + secondsString;
    }

}

timer.html

<div *ngIf="timer">
    <ion-item class="no-bottom-border item">
        <button ion-button *ngIf="timeInSeconds && timeInSeconds > 0" large full clear class="timer-button timer-text">{{timer.displayTime}}</button>
    </ion-item>
    <ion-item class="no-bottom-border" *ngIf="timeInSeconds && timeInSeconds > 0">
        <button ion-button icon-left clear color="danger" small (click)="initTimer()" item-left *ngIf="!timer.runTimer && (timer.hasStarted || timer.hasFinished) || timer.hasFinished">
            <ion-icon name="refresh"></ion-icon>
            Reset
        </button>
        <button ion-button icon-left clear small color="primary" (click)="pauseTimer()" item-right *ngIf="timer.runTimer && timer.hasStarted && !timer.hasFinished">
            <ion-icon name="pause"></ion-icon>
            Pause
        </button>
        <button ion-button icon-left clear small color="primary" (click)="resumeTimer()" item-right *ngIf="!timer.runTimer && timer.hasStarted && !timer.hasFinished">
            <ion-icon name="play"></ion-icon>
            Resume
        </button>
        <button ion-button icon-left clear small color="primary" (click)="startTimer()" item-right *ngIf="!timer.hasStarted">
            <ion-icon name="play"></ion-icon>
            Start
        </button>
    </ion-item>
</div>

【讨论】:

  • 我明白你说的。我需要明天@我的办公室试试这个,但是如果每个计时器都有相同的时间会发生什么?假设在我的订阅逻辑结束时弹出页面,这是否意味着我会弹出 n 次页面?(作为列表页面中的扇区数?)
猜你喜欢
  • 2019-03-08
  • 1970-01-01
  • 2016-11-28
  • 1970-01-01
  • 2017-05-10
  • 1970-01-01
  • 2017-12-24
  • 1970-01-01
  • 2020-06-01
相关资源
最近更新 更多