user1724147
user1724147

Reputation: 51

NgbModal opens very slowly for *some* modal windows

I'm using [email protected]. Some modal dialogs are opening very quickly, while others are opening extremely slowly (sometimes taking 15 seconds to open). The slow behavior is: The modal window shows with a maximum width regardless of the size selected, but has not modal-body content (yet). Approximately 15 seconds later, the modal window resizes to the requested size, and then populates with the modal-body as expected. I have compared the modal components that work fine with the modal components that don't, and see very few differences aside from functionality differences like you would expect. I've tried changing the "backdrop", I've tried setting the "container", I've tried converting the modal between an in-line ng-template and a separate component. Nothing is changing the behavior of the slow modals. Does anyone have any ideas?

Upvotes: 1

Views: 1581

Answers (2)

Kragh
Kragh

Reputation: 312

This could be caused by change detection issues. Try to open modal in change detection zone.

Inject Zone:

constructor(
    private modalService: NgbModal,
    private zone: NgZone,
  ) { }

and wrap modalService.open with zone.run:

confirmDelete(user: DSUser): void {
    this.zone.run(() => {
      const modalRef = this.modalService.open(ConfirmModalComponent, {
        backdrop: true,
        centered: true,
      }).componentInstance;

      modalRef.message = `<strong>Are you sure you want to delete <span class="text-primary">"${user.name.firstName} ${user.name.lastName}"</span> profile?</strong>`;
      modalRef.confirmCallback = () => this.deleteUser.emit(user);
    });
  }

Upvotes: 2

user1724147
user1724147

Reputation: 51

I am using ngx-simplemde, and launching a modal from a custom toolbar item in the markdown editor. For some reason, when launching a modal, popover, or tooltip from within the markdown editor, it behaves very slowly. I had to abstract my logic out of the custom ngx-simplemde toolbar button and trigger the modal being opened from outside the ngx-simplemde custom toolbar item. This was fairly difficult to figure out, as I had to create a hidden button, and then trigger the hidden button using the DOM's .click() method, and the ngClick of the button was setup to initiate the modal popup. Not ideal, fairly hacky, but it works now.

component.html

  <simplemde [(ngModel)]="value" [options]="{ toolbar: toolbar }" (ngModelChange)="valueChange.emit($event)" #smde></simplemde>
  <button type="button" class="btn btn-primary" (click)="insertImage()" style="display: none" #buttonElement>Test</button>

component.ts

  createImageListToolbar() {
    return {
      name: 'image-list',
      className: 'fas fa-images',
      title: this.imageListButtonTitle,

      // This action is called when the user clicks the button
      // It will open the imageListModal that is embedded in the HTML of this component
      // When the modal closes, the user will have selected the image they want inserted
      action: async () => {
        this.buttonEle.nativeElement.click();
      }
    };
  }

  async insertImage() {
    const image = await this.modalService.getMediaSelection(this.implementationGuideId, this.mediaReferences);

    const doc = this.simplemde.Instance.codemirror.getDoc();
    const cursor = doc.getCursor();

    const altTag = image.title ? `alt="${image.title}" ` : '';
    const replaceText = `<table><tr><td><img src="${image.name}" ${altTag}/></td></tr></table>`;
    doc.replaceRange(replaceText, cursor);
  }

modal.service.ts:

  async getMediaSelection(implementationGuideId?: string, mediaReferences?: MediaReference[]): Promise<ImageItem> {
    const modalRef = this.modalService.open(MediaSelectionModalComponent, { container: 'body', backdrop: 'static' });
    modalRef.componentInstance.implementationGuideId = implementationGuideId;
    modalRef.componentInstance.mediaReferences = mediaReferences;
    return await modalRef.result;
  }

Upvotes: 1

Related Questions