简体   繁体   中英

Angular NgbModal dialog not showing up

I am creating an idle timeout warning message for my page. However it doesn't seem to load properly. The screen appears frozen, but the dialog is not displaying. In another system the dialog is displaying after sometime. Please find the sample code below. When the time left is below 20 secs isItTimeToShowPopUp will attempt to open the dialog. I can see it getting triggered but no display.

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';

import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
@NgModule({
  declarations: [
    AppComponent,
    LoginComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    NgbModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts

import { Component, Input, OnInit, NgZone, ChangeDetectorRef, ViewChild, TemplateRef, AfterViewInit  } from '@angular/core';
import { fromEvent, merge, interval, Observable, of, Subscription } from 'rxjs'
import { switchMap, take, skipWhile, takeLast, skipUntil, tap } from 'rxjs/operators'
import { NgbModal, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, AfterViewInit {
  @Input() name: string;
@ViewChild('sessionWarning') sessionWarning : any;
  // here we need to give the time in second ie how long we want the inactivity timer default i have kept as 5 sec
  inactivityTime: number = 30;

  timeLapsedSinceInactivity: number = 0;
  minute: number = this.padZero(0);
  seconds: number = this.padZero(0);
  subscription?: Subscription;
  observeable$?: Observable<any>;
  mergedObservable$?: Observable<any>;
  sessionWarningDisplayed? : boolean = false;
  closeResult? : string = "";
  public inactivityTimerEvent: Array<any>[] = [[document, 'click'], [document, 'wheel'], [document, 'scroll'], [document, 'mousemove'], [document, 'keyup'], [window, 'resize'], [window, 'scroll'], [window, 'mousemove']];

  constructor(public _ngZone: NgZone,
    public _cd: ChangeDetectorRef,
    private _modalService: NgbModal) {

  }
ngAfterViewInit(){
  this.createObserable();
}
  ngOnInit() {

    let observableArray$: Observable<any>[] = [];
    this.inactivityTimerEvent.forEach(x => {
      observableArray$.push(fromEvent(x[0], x[1]))
    })
    this.mergedObservable$ = merge(...observableArray$);

    // this.createObserable();
  }
  open() {

    console.log("opening modal")
    this._modalService.open(this.sessionWarning, {ariaLabelledBy: 'modal-basic-title'}).result.then((result) => {
      this.closeResult = `Closed with: ${result}`;
    }, (reason) => {
      this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
    });
  }

  private getDismissReason(reason: any): string {
    if (reason === ModalDismissReasons.ESC) {
      return 'by pressing ESC';
    } else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
      return 'by clicking on a backdrop';
    } else {
      return `with: ${reason}`;
    }
  }

  createObserable(): void {
    this._ngZone.runOutsideAngular(() => {

      this.observeable$ = this.mergedObservable$
      .pipe(
        switchMap(ev => interval(1000).pipe(take(this.inactivityTime))),

        tap(value => this.isItTimeToShowPopUp(value)),

        skipWhile((x) => {
          this.timeLapsedSinceInactivity = x;
          return x != this.inactivityTime - 1
        })
      );

      this.subscribeObservable();
    })

  }

  isItTimeToShowPopUp(val: number) {
    let timeLeftForInactive = this.inactivityTime - val;
    if (timeLeftForInactive <= 20) {
      this.timeLapsedSinceInactivity = timeLeftForInactive;
      this.minute = this.padZero(Math.floor(timeLeftForInactive / 13));
      this.seconds = this.padZero(timeLeftForInactive % 13);
      this._cd.detectChanges();
      if(!this.sessionWarningDisplayed)
      {
        this.sessionWarningDisplayed = true;
        this.open()
      }
    }
  }

  subscribeObservable() {
    this.subscription = this.observeable$.subscribe((x) => {
      console.log(`subscribed for ${x + 1} sec`);
      this.unsubscribeObservable();
    })
  }
  padZero(digit: any) {
    return digit <= 9 ? '0' + digit : digit;
  }

  unsubscribeObservable() {
    console.log('  unsubscribed')
    this.subscription.unsubscribe();
  }

}

app.component.html

<router-outlet></router-outlet>
<ng-template #sessionWarning let-c="close" let-d="dismiss" let-modal>
  <div class="modal-header">
    <h4 class="modal-title">Modal title</h4>
    <button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body">
    <p>One fine body&hellip;</p>
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-secondary" (click)="c('Close click')">Close</button>
  </div>
</ng-template>

app.component.css

@import "~bootstrap/dist/css/bootstrap.css";

I have verified from the developer tools that bootstrap.css is loaded in to the style.css

i was able to make it work by wrapping the modal open statement within _ngZone.run(()=>{//Code goes here})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM