2

I am developing an Angular 7 app and in this app I am using the WYSIWYG editor library called Froala.

I have added a custom button to the toolbar and now I want to call a method in the same class the user clicks on this button (to open up a custom modal). I use the code below but I get an error saying it does not find the openPictureModal method.

$.FroalaEditor.DefineIcon('imagePicker', {NAME: 'info'});
    $.FroalaEditor.RegisterCommand('imagePicker', {
      title: 'Image picker',
      focus: false,
      undo: false,
      refreshAfterCallback: false,
      callback: function (data) {
        this.openPictureModal();
      }
    });

I get this error:

Uncaught TypeError: this.openPictureModal is not a function

This is my modal method:

openPictureModal() {
    const modalRef = this.modalService.open(PictureManageComponent, { size: 'lg' });
          modalRef.componentInstance.formFinished.subscribe(($event) => {
            modalRef.close();
          });
  }

How can I call custom methods in the same class from a custom button?

Jonathan Clark
  • 19,726
  • 29
  • 111
  • 175
  • 1
    Define the callback as an arrow function: `callback: (data) => { this.openPictureModal(); }`. – ConnorsFan Feb 27 '19 at 14:26
  • Thanks, in a way it works but the method I call (a call to open a modal) does not fire until I click the editor area. Very strange. It does not seem to call the method directly. I have updated my question with the method code. – Jonathan Clark Feb 27 '19 at 14:32
  • I think it´s because when the modal is supposed to open the editor loses focus. That is why it works when I click on the editor. – Jonathan Clark Feb 27 '19 at 14:48

1 Answers1

3

There are two issues in your code. The first one, which is very common, is that this is lost inside of the callback. Defining the callback as an arrow function should take care of that problem. See this question for more details.

The second issue is more subtle. The callback, being a jQuery event handler, is probably called outside of the Angular zone. As a consequence, it does not trigger change detection. You can wrap the callback code in NgZone.run() to solve that problem.

The resulting code would be something like this:

import { NgZone } from '@angular/core';

constructor(private ngZone: NgZone) { }

...

initializeFroala() {
  $.FroalaEditor.DefineIcon('imagePicker', {NAME: 'info'});
  $.FroalaEditor.RegisterCommand('imagePicker', {
    title: 'Image picker',
    focus: false,
    undo: false,
    refreshAfterCallback: false,
    callback: (data) => {            // Define the callback as arrow function
      this.ngZone.run(() => {        // Run the callback code in Angular zone
        this.openPictureModal();
      });
    }
  });
}
ConnorsFan
  • 70,558
  • 13
  • 122
  • 146
  • That worked perfectly. No delay, no strange behaviour! Now I only need to be able to insert at the exact right place (user selection). Problem is keeping the selection when the modal opens. – Jonathan Clark Feb 28 '19 at 09:26