Search code examples
angularngx-modal

Angular2: overwrite img command in ng2-ckeditor


I have a page that have ckeditor in there. I use ng2-ckeditor and ngx-modal. This is my template:

<div>
    <ckeditor 
        id="questionContent"
        name="questionContent"
        [(ngModel)]="question.content" 
        (change)="onChange($event)" 
        (ready)="onReady($event)"
        (focus)="onFocus($event)" 
        (blur)="onBlur($event)" debounce="500">
    </ckeditor>
</div>
....//Some stuff there
<!--Modal-->
<modal #uploadModal [closeOnEscape]="false" [closeOnOutsideClick]="false">
    <modal-header>
        <h4 class="modal-title pull-left">{{ 'QUESTIONS' | translate }}</h4>
    </modal-header>
    <modal-content>
        <div class="drag-n-drop-container"
            ngFileDrop
            [options]="options"
            (onUpload)="handleUpload($event)"
            [ngClass]="{'file-over': hasBaseDropZoneOver}"
            (onFileOver)="fileOverBase($event)">
        <h1>Drag & Drop</h1>
        <label class="upload-button">
            <input type="file"
                class="hidden"
                ngFileSelect
                [options]="options"
                (onUpload)="handleUpload($event)">
            Browse
        </label>
        </div>
    </modal-content>
    <modal-footer>
        <button class="btn btn-default pull-right cancel" (click)="uploadModal.close()">
            <i class="fa fa-times"></i>
            {{ 'BUTTON_CLOSE' | translate }}</button>
    </modal-footer>
</modal>

My situation is try to overwrite image dialog of ckeditor. So in my component I will do this:

import {
  Component, OnInit, ViewChild, ViewChildren, AfterViewChecked,
  AfterViewInit, Renderer, QueryList, ViewEncapsulation
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router, ActivatedRoute, Params } from '@angular/router';

import { Modal } from 'ngx-modal';
import { CKButtonDirective, CKEditorComponent } from 'ng2-ckeditor';

declare var CKEDITOR: any;
@Component({
  selector: 'question-edit',
  templateUrl: './question-edit.component.html',
  styleUrls: [
    './question-edit.style.css'
  ],
  encapsulation: ViewEncapsulation.None
})
export class EditQuestionComponent implements OnInit, AfterViewChecked, AfterViewInit {
  @ViewChildren('answers') answerInputs: QueryList<any>;
  @ViewChild('uploadModal') public uploadModal: Modal;

  private editor: any;
  constructor(private rd: Renderer) { }

  ngOnInit() {

  };

  registerCKEditorCommands(editor: any, uploadModal: Modal) {
    let self = this;
    editor.addCommand("image", {
      exec: self.onUploadImage
    });
  };

  ngAfterViewInit() {
    let self = this;
    setTimeout(function () {
      for (var instanceName in CKEDITOR.instances) {
        self.editor = CKEDITOR.instances[instanceName];
        self.editor.on("instanceReady", function (ev: any) {
          let _editor = ev.editor;
          self.registerCKEditorCommands(_editor, self.uploadModal);
        });
      }
    });
  };

  onUploadImage(editor: any) {
    this.uploadModal.open();
  };
}

All work fine except when I click image button in ckeditor toolbar. It will invoke function onUploadImage() but this.uploadModal is undefined. If we try to printout this.uploadModal in function ngAfterViewInit() it give correct value and we can open dialog there.

How I can handle open dialog in function onUploadImage? Thank in advance.


Solution

  • I think any of these options should work for you because this way context will be referenced to your component instance:

    1) bind

    a)

    editor.addCommand("image", {
      exec: this.onUploadImage.bind(this)
    });
    

    b)

    export class EditQuestionComponent {
      constructor() {
        this.onUploadImage = this.onUploadImage.bind(this);
      }
      ...
      editor.addCommand("image", {
        exec: this.onUploadImage
      });
    

    2) arrow function

    editor.addCommand("image", {
      exec: (editor) => this.onUploadImage(editor)
    });
    

    3) instance arrow function

    editor.addCommand("image", {
      exec: this.onUploadImage
    });
    ...
    onUploadImage = (editor: any) => {
      this.uploadModal.open();
    };
    

    See also