froala / angular-froala-wysiwyg

Angular 4, 5, 6, 7, 8 and 9 plugin for Froala WYSIWYG HTML Rich Text Editor.
https://froala.com/wysiwyg-editor
734 stars 201 forks source link

Cannot access editor instance in initialized event #310

Open emeryowa opened 5 years ago

emeryowa commented 5 years ago

I'm in the process of upgrading the Froala editor in my app to v3

I have setup a function on the initalized event. Previous I could access the editor instance with the function param

'froalaEditor.initalized': function(e, editor) {
    console.log(editor); // this is the editor instance
}

How can I access the editor instance in v3? I believe the function params are omitted now in favor of using this. However this is undefined in the initalized event

'initialized': function(e, editor)) {
    console.log(editor); // undefined
    console.log(this); // undefined
}

See stackblitz: https://stackblitz.com/edit/angular-rq1h29

sfabriece commented 5 years ago

I have made a PR exposing the editor here https://github.com/froala/angular-froala-wysiwyg/pull/309. Upvote it so that It can land asap.

Meanwhile, I have just copied the directive and customized it to fit my purpose for now @emeryowa

tiaguinho commented 5 years ago

It's not necessary to expose the editor. This is can be done like:

<div  [froalaEditor] (froalaInit)="initializeLink($event)">Froala Editor</div>
initializeLink(controls) {
    controls.initialize();
    this.editor = controls.getEditor();
}
sfabriece commented 5 years ago

Thanks for that @tiaguinho. It's probably not a bad idea to expose the editor from the directive. In that case you don't have to use froalaInit if you are already querying the template for the directive.

emeryowa commented 5 years ago

How would I be able to access the editor with this solution, when I set the intialized event callback on the editor config? With this ?


public options: Object = {
    placeholderText: 'Edit Your Content Here!',
    charCounterCount: false,
    events: {
      'initialized': function(e, editor) {
        console.log('init');
        console.log(editor);
        console.log(this);
      }
    }
  }```
Supratentorial commented 5 years ago

I am also using code similar to @emeryowa to configure events which require a reference to the editor:

options: Object = {
    toolbarButtons: ['bold', 'italic', 'underline'],
    toolbarInline: true,
    charCounterCount: false,
    quickInsertTags: [],
    events: {
      'froalaEditor.initialized': (e, editor) => {
        this.tribute.attach(editor.el);
        editor.events.on(
          'keydown',
          (event: any) => {
            if (event.which === $.KEYCODE.ENTER && this.tribute.isActive) {
              return false;
            }
          },
          true
        );
      }
    }
  };

This is no longer working in v3. Also, with the removal of the dependency on jQuery in v3, what is the preferred way of identifying the key which was pressed?

emeryowa commented 5 years ago

Is there any news/timeline on a definitive solution for this? This is blocking us from upgrading to version 3.

sfabriece commented 5 years ago

the way to access events have changed in froala: https://www.froala.com/wysiwyg-editor/docs/events @emeryowa

emeryowa commented 5 years ago

@sfabriece I use the syntax as described in the docs in my stackblitz, but this is undefined

sfabriece commented 5 years ago

I'm not sure what is going on in that case @emeryowa. Have you tried using froalaInit to get the editor and do what you want to do in the handler?

https://stackblitz.com/edit/angular-dam9ws?file=src/app/app.component.ts

Does that help @emeryowa ?

Supratentorial commented 5 years ago

I have used the froalaInit to obtain a reference to the editor:

  public initializeEditor(initControls) {
    initControls.initialize();
    this.editor = initControls.getEditor();
    this.editor.events.on('keydown', (event) => { console.log(event.which); }, false);
    console.log(this.editor);
    console.log(this);
  }

The issue is how to do the dynamic event binding as I get the following error when the above is run:

Cannot read property 'on' of undefined

What is the syntax for dynamic event binding using the "manual initialization" method?

emeryowa commented 5 years ago

I'm not sure what is going on in that case @emeryowa. Have you tried using froalaInit to get the editor and do what you want to do in the handler?

https://stackblitz.com/edit/angular-dam9ws?file=src/app/app.component.ts

Does that help @emeryowa ?

@sfabriece When I use this approach the code I want to use in the init handler doesn't work See https://stackblitz.com/edit/angular-pgh7hy?file=src/app/app.component.ts

init(e: any){
    e.initialize();
    this.editor = e.getEditor();
    console.log('editor ',this.editor);

    // ISSUE: "Cannot set property 'sanitizeURL' of undefined"
    this.editor.helpers.sanitizeURL = function(url){
      return url;
    };

    // ISSUE: editor still editable after calling this
    this.editor.edit.off();

    // ISSUE: never logged when dropping image in the wysiwyg
    this.editor.events.on('drop', function() {
      console.log('drop');
      return false;
    }, true);     
}

I'm also confused: why should we use this approach instead of the approach via the config as stated in the docs?

langereissilvio commented 5 years ago

I have used the froalaInit to obtain a reference to the editor:

  public initializeEditor(initControls) {
    initControls.initialize();
    this.editor = initControls.getEditor();
    this.editor.events.on('keydown', (event) => { console.log(event.which); }, false);
    console.log(this.editor);
    console.log(this);
  }

The issue is how to do the dynamic event binding as I get the following error when the above is run:

Cannot read property 'on' of undefined

What is the syntax for dynamic event binding using the "manual initialization" method?

I have a similar issue in Angular. This happens because the editor isn't fully initialized when you call 'events.on'. If the initialization was a promise, we could wait for it to be fully loaded.

Supratentorial commented 5 years ago

Any update on this issue? This is blocking upgrade to V3 for us.

hoi4 commented 5 years ago

We have the same problem..

williamjburger commented 5 years ago

This is also preventing us from using V3.

Netix-Liu commented 5 years ago

I'm using Froala via Angular package: angular-froala-wysiwyg@3.0.3-1. seems getEditor function is not work anymore, and neither did the property: languages from option.

did anyone encountered the same situation?

emeryowa commented 5 years ago

To anyone's interest:

I contacted Froala support directly regarding this issue and I've finally got a sort of solution for this problem. The issue lies with the usage of arrow functions. The workaround is to use standard functions. Then this will refer to the instance of the editor.

public options: Object = {
    events: {
      'initialized': function() {
          console.log(this);
        }
      }
  }

See also https://stackblitz.com/edit/angular-dake2l

Note that I've only tested this in version 3.0.5

Supratentorial commented 5 years ago

Can confirm that emeryowa's fix works, but note that it works only with 3.0.5. I was still getting undefined on version 3.0.2.

@emeryowa Thank you so much for the follow up.

FrancisGroleau commented 5 years ago

what about the getEditor() fonction ? I try to do something similar to @emeryowa The only solution i found was to wait a bit so the initialization is done something like

setTimeout(() => { editor.image.insert(someImageUrl);  }, 100);

otherwise editor.image is undefined

qmakani commented 4 years ago

To anyone's interest:

I contacted Froala support directly regarding this issue and I've finally got a sort of solution for this problem. The issue lies with the usage of arrow functions. The workaround is to use standard functions. Then this will refer to the instance of the editor.

public options: Object = {
    events: {
      'initialized': function() {
          console.log(this);
        }
      }
  }

See also https://stackblitz.com/edit/angular-dake2l

Note that I've only tested this in version 3.0.5

I've been able to get the editor instance using this approach. I can even see the events option printed on console when I print this. But when I try to access this.events, I get undefined. Don't know what's going on.

ansh-les commented 4 years ago

To anyone's interest: I contacted Froala support directly regarding this issue and I've finally got a sort of solution for this problem. The issue lies with the usage of arrow functions. The workaround is to use standard functions. Then this will refer to the instance of the editor.

public options: Object = {
    events: {
      'initialized': function() {
          console.log(this);
        }
      }
  }

See also https://stackblitz.com/edit/angular-dake2l Note that I've only tested this in version 3.0.5

I've been able to get the editor instance using this approach. I can even see the events option printed on console when I print this. But when I try to access this.events, I get undefined. Don't know what's going on.

same issue here

qmakani commented 4 years ago

To anyone's interest: I contacted Froala support directly regarding this issue and I've finally got a sort of solution for this problem. The issue lies with the usage of arrow functions. The workaround is to use standard functions. Then this will refer to the instance of the editor.

public options: Object = {
    events: {
      'initialized': function() {
          console.log(this);
        }
      }
  }

See also https://stackblitz.com/edit/angular-dake2l Note that I've only tested this in version 3.0.5

I've been able to get the editor instance using this approach. I can even see the events option printed on console when I print this. But when I try to access this.events, I get undefined. Don't know what's going on.

same issue here

Yeah, this solution worked for me as well. Another problem I faced was that the editor instance although available through this method wasn't completely initialized. Like the events part wasn't accessible directly inside the initialized handler. I came up with a hack to pass the the "this" to a setTimeout with 100 ms delay, where it would be completely initialized.

ansh-les commented 4 years ago

Yeah, this solution worked for me as well. Another problem I faced was that the editor instance although available through this method wasn't completely initialized. Like the events part wasn't accessible directly inside the initialized handler. I came up with a hack to pass the the "this" to a setTimeout with 100 ms delay, where it would be completely initialized.

Yes I faced the same issue. I had to disable the editor when it was initialized but the edit property of the editor was not available in the initialized event. I did not think of the setTimeout "hack" lol. I just replaced the initialized event with edit.on

qmakani commented 4 years ago

Yeah, this solution worked for me as well. Another problem I faced was that the editor instance although available through this method wasn't completely initialized. Like the events part wasn't accessible directly inside the initialized handler. I came up with a hack to pass the the "this" to a setTimeout with 100 ms delay, where it would be completely initialized.

Yes I faced the same issue. I had to disable the editor when it was initialized but the edit property of the editor was not available in the initialized event. I did not think of the setTimeout "hack" lol. I just replaced the initialized event with edit.on

My specific use case was to disable new-line when 'enter' key was pressed in certain scenarios. So I had to make sure my keydown event was bound before froala's. This is the only way I was able to do it in the time I had. Maybe there's a better way.

ecappa commented 4 years ago

What a brilliant idea to put this in... this. That's just refer to the Angular Component... :/

ecappa commented 4 years ago

What a brilliant idea to put this in... this. That's just refer to the Angular Component... :/

The answer to my sarcastic comment is here : https://github.com/froala/angular-froala-wysiwyg/issues/154 Using a local copy of the component instance and a

component.ngZone.run(() => {
          component...{whateveryoiuwant};
        });
Khushbu-2112 commented 3 years ago

Hello, Below are the changes that I've done to fix this error.

Froala - V3, Angular - V7.

HTML

<div 
        [froalaEditor]="froalaOptions"
        [(froalaModel)]="description"
        name="description"
        (froalaInit)="created($event)"
      ></div>

TS

editorInstance;
created(event) {
     event.initialize();
      this.editorInstance = event.getEditor();
}  
onVariableBtn(data) { 
       this.editorInstance.html.insert(data.id, false); 
       this.form.value.description = this.editorInstance.html.get(false);
}

Hope this is helpful if anyone is facing the same issue.