3

我在 Ng-Idle、Material 6 和 Angular 6 中发现了一个问题

"@ng-idle/core": "^6.0.0-beta.3"
"@ng-idle/keepalive": "^6.0.0-beta.3"
"@angular/core": "^6.1.9"
"@angular/cdk": "^6.4.7"
"@angular/material": "^6.4.7"

场景

当用户空闲时,对话框(弹出窗口)显示倒计时,直到用户退出系统。如果用户在退出鼠标活动之前返回,倒计时将停止并且对话框将关闭/消失。

问题

但是,在 Angular 5 中,此功能在我升级到 Angular 6 之前运行良好。当用户在 之前返回时onTimeout,它会触发 ,onIdleEnd但对话框不会在鼠标活动时消失。我创建了一个 Angular 6 应用程序来复制该问题。我正在尝试确定这是 Ng-Idle 还是 Angular 问题。

Stackblitz 与 Ng-Idle

Stackblitz 显示 Mat-Dialog 在 10 秒倒计时后关闭

Github

有没有人遇到过这个问题?

4

2 回答 2

5

我遇到过同样的问题。我通过推动角度的变化来解决它。

第一的:

{ AppplicationRef } from '@angular/core';

在组件的构造函数中添加 ChangeDetectorRef:

constructor(private appRef: ApplicationRef)

然后在 onIdleEnd 上调用它:

this.idle.onIdleEnd.subscribe(() => {
    this.showModal = false;
    this.appRef.tick();
});

StackBlitz 解决方案

于 2018-12-20T15:31:22.173 回答
1

好的,所以我无法发表评论,因为我还没有声誉,但我想分享我是如何解决这个问题的。我所做的是在我的对话框标题/内容周围创建一个父 <div> 元素,该元素在单击时调用 closeMe() 函数。这个 closeMe() 调用 'this.dialogRef.close()' 函数,它实际上确实关闭了对话框。

当 ng2-idle 触发 onIdleEnd observable 时,我模拟了对该父 div 的点击。为此,我需要将 Idle 对象“注入”到对话框中。

我的对话框 component.ts 文件:

import { Component, OnInit, Inject, ViewChild, ElementRef } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { Idle } from '@ng-idle/core';

@Component({
  selector: 'idle-timeout-warning-modal',
  templateUrl: './idle-timeout-warning.component.html',
  styleUrls: ['./idle-timeout-warning.component.css'],
})
export class IdleIimeoutWarningComponent implements OnInit {
  private idle: Idle;

  public countdown: number;

  //Need this in order to close the dialog box on idle end. This is because, for some reason,
  //I cannot do a this.dialogRef.close() in the onIdleEnd subscription.
  @ViewChild('closeMeDiv') closeMeDiv: ElementRef;

  constructor(
    public dialogRef: MatDialogRef<IdleIimeoutWarningComponent>,
    @Inject(MAT_DIALOG_DATA) public data: any, //Data is: {"idleObj":<idle object>, "timeout":<timeoutPeriodSec (integer)>}
  ) { 
    this.idle = data.idleObj;
    this.countdown = data.timeout;
  }

  ngOnInit() { 
    this.idle.onTimeoutWarning.subscribe((countdown: number) => {
      this.countdown = countdown;
    });
    this.idle.onIdleEnd.subscribe(() => { 
      this.closeMeDiv.nativeElement.click();
    });
  }

  closeMe() {
    this.dialogRef.close();
  }
}

我的对话框html文件:

<div #closeMeDiv (click)="closeMe()">
    <div mat-dialog-title>
        <h3>Please move the mouse or press any key</h3>
        <hr />
    </div>

    <div mat-dialog-content>
        <p>
            You'll be logged out in <span class="idle-label idle-label-warning">{{countdown}}</span>
            second<span *ngIf="countdown != 1">s</span>.
        </p>
    </div>
</div>

然后在空闲设置函数中(在我拥有的另一个服务中,在构造函数参数中注入了 ``this.idle```):

let idleStartSec:number = 5;
let timeoutPeriodSec:number = 5;

// sets an idle timeout - will trigger timeout period
this.idle.setIdle(idleStartSec);
// sets a timeout period. after this amount of inactivity, the user will be considered timed out.
this.idle.setTimeout(timeoutPeriodSec);
// sets the default interrupts, in this case, things like clicks, scrolls, touches to the document
this.idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);

this.idle.onIdleStart.subscribe(() => { //Fires when timeout is about to start
  this.dialogRef = this.dialog.open(IdleIimeoutWarningComponent, {
    panelClass: 'modal-lg',
    data: {"idleObj":this.idle, "timeout":timeoutPeriodSec}
  });
});

this.idle.onTimeout.subscribe(() => {
  this.dialogRef.close();
  //Do other stuff here
});

奇怪的是,直接调用this.dialogRef.close();在 onTimeout 中有效,但在 onIdleEnd 中无效。

无论如何,希望这会有所帮助,直到问题得到解决。

于 2019-01-09T19:08:07.790 回答