【问题标题】:Having issues with ng-idle/core onIdleEnd & Mat-Dialogng-idle/core onIdleEnd & Mat-Dialog 有问题
【发布时间】:2018-10-08 20:16:13
【问题描述】:

我在 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 但对话框不会t 在鼠标活动时消失。我创建了一个 Angular 6 应用程序来复制该问题。我正在尝试确定这是 Ng-Idle 还是 Angular 问题。

Stackblitz with Ng-Idle

Stackblitz showing Mat-Dialog closing after 10 second countdown

Github

有人遇到过这个问题吗?

【问题讨论】:

    标签: angular angular-material2 ng-idle


    【解决方案1】:

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

    第一:

    { AppplicationRef } from '@angular/core';
    

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

    constructor(private appRef: ApplicationRef)
    

    然后在 onIdleEnd 上调用它:

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

    StackBlitz solution.

    【讨论】:

    • 它对我不起作用!我在 Stackblitz 上更新了代码,但没有任何效果!
    • 我什至尝试将ChangeDetectionStrategy 显式更新为OnPush
    • 所以你对 ChangeDetection 的回答就是所需要的。我会用我所做的更新你的答案。
    【解决方案2】:

    好的,所以我无法发表评论,因为我还没有声誉,但我想分享一下我是如何解决这个问题的。我所做的是在我的对话框标题/内容周围创建一个父

    元素,该元素在单击时调用 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 中无效。

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

    【讨论】:

    • 感谢您的贡献,我想出了一个更简单的方法。
    • 没问题!愿意分享吗?我很想知道!
    • 这是公认的答案。我用 ApplicationRef 更新了 ChangeDetection。
    猜你喜欢
    • 2018-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    相关资源
    最近更新 更多