Ckeditor5-angular: CKEditor uses window object, which doesn't work on Angular Universal

Created on 30 Apr 2019  Â·  14Comments  Â·  Source: ckeditor/ckeditor5-angular

I'm trying to setup Angular Universal for my project, it seems CKEditor is using window object that doesn't on Angular Universal project https://angular.io/guide/universal

!function(t){t.en=Object.assign(t.en||{},{a:"Cannot upload file:",b:"Bold",c:"Italic",d:"Insert image or file",e:"image widget",f:"Block quote",g:"Full size image",h:"Side image",i:"Left aligned image",j:"Centered image",k:"Right aligned image",l:"Choose heading",m:"Heading",n:"Insert image",o:"Numbered List",p:"Bulleted List",q:"Insert table",r:"Header column",s:"Insert column left",t:"Insert column right",u:"Delete column",v:"Column",w:"Header row",x:"Insert row below",y:"Insert row above",z:"Delete row",aa:"Row",ab:"Merge cell up",ac:"Merge cell right",ad:"Merge cell down",ae:"Merge cell left",af:"Split cell vertically",ag:"Split cell horizontally",ah:"Merge cells",ai:"Enter image caption",aj:"Upload failed",ak:"media widget",al:"Insert media",am:"The URL must not be empty.",an:"This media URL is not supported.",ao:"Link",ap:"Could not obtain resized image URL.",aq:"Selecting resized image failed",ar:"Could not insert image 

ReferenceError: window is not defined
duplicate

Most helpful comment

Hi @kirill-chirkov-at-clouty and anyone else that is still bumping into this problem.

I've just found a solution that allows you to conditionally import the editor via require().

Is a workaround similar as @thefliik suggested in https://github.com/angular/angular/issues/24551#issuecomment-397862707 for @angular/elements.

export class MyComponent{
   Editor;
   isBrowser = false;
   constructor((PLATFORM_ID) platformId: Object) {
      this.isBrowser = isPlatformBrowser(platformId);
      if (this.isBrowser) {
         const ClassicEditor = require('@ckeditor/ckeditor5-build-classic');
         this.Editor = ClassicEditor;
         this.Editor.defaultConfig = {
            toolbar: {
               items: ['yourListOfButtons'],
            },
         };
      }
   }
}

And keep the component tag as the documentation suggests...

<ckeditor
   *ngIf="isBrowser" 
   [editor]="Editor"
   [(ngModel)]="yourModel" 
   (change)="onChange($event)" 
   (ready)="onReady($event)">
</ckeditor>

Hope it helps! :smiley:

All 14 comments

@ma2ciek, could you take a look at this one?

Yep, I'd close this issue in favor of ckeditor/ckeditor5#1511, @rezonjov, please follow this thread to follow the progress in this topic.

There's also a hack like that one: https://github.com/ckeditor/ckeditor5/issues/1499#issuecomment-46006334 that you could use until the issue has been resolved.

Also, remember to vote on the mentioned issue to increase its priority.

Hi @kirill-chirkov-at-clouty and anyone else that is still bumping into this problem.

I've just found a solution that allows you to conditionally import the editor via require().

Is a workaround similar as @thefliik suggested in https://github.com/angular/angular/issues/24551#issuecomment-397862707 for @angular/elements.

export class MyComponent{
   Editor;
   isBrowser = false;
   constructor((PLATFORM_ID) platformId: Object) {
      this.isBrowser = isPlatformBrowser(platformId);
      if (this.isBrowser) {
         const ClassicEditor = require('@ckeditor/ckeditor5-build-classic');
         this.Editor = ClassicEditor;
         this.Editor.defaultConfig = {
            toolbar: {
               items: ['yourListOfButtons'],
            },
         };
      }
   }
}

And keep the component tag as the documentation suggests...

<ckeditor
   *ngIf="isBrowser" 
   [editor]="Editor"
   [(ngModel)]="yourModel" 
   (change)="onChange($event)" 
   (ready)="onReady($event)">
</ckeditor>

Hope it helps! :smiley:

@hjaraujof thanks for the great solution, that surely helps!

Trying to follow this @kirill-chirkov-at-clouty @hjaraujof using a couple of inhouse tools. Currently it's not seeing the ckeditor component, which I believe comes from the CKEditorModule. Any ideas on what I'm doing wrong?

image

  ngOnInit() {
    if (isPlatformBrowser(this.platformId)) {
      const BalloonEditor = require('@ckeditor/ckeditor5-build-balloon');
      this.Editor = BalloonEditor;
      this.Editor.defaultConfig = this.editorConfig;
    }
  }
  <ckeditor
    *mIfBrowser
    [ngModel]="content"
    (ngModelChange)="onContentChanged($event)"
    [editor]="Editor"
    [config]="editorConfig"
  ></ckeditor>

@bhayward93 Did you import required module?

import { CKEditorModule } from '@ckeditor/ckeditor5-angular';

@NgModule({
    imports: [
        ...
        CKEditorModule,
    ],
})
export class SomeModule { }

Thanks, that did the trick - I was being a bit dumb and had left in a require for CKEditorModule when I was playing around.

That said I ended up having to ditch BalloonEditor for ClassicEditor (which is fine because its for a PoC).

@hjaraujof thank you for the great solution!

I did that but I got another issue after implementation:

node_modules/@ckeditor/ckeditor5-watchdog/src/editorwatchdog.js:12
import { throttle, cloneDeepWith, isElement } from 'lodash-es';
       ^

SyntaxError: Unexpected token {
    at Module._compile (internal/modules/cjs/loader.js:723:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Module.require (internal/modules/cjs/loader.js:692:17)
    at require (internal/modules/cjs/helpers.js:25:18)

Hm. The new version of ckeditor5-angular  contains an import to the EditorWatchdog class, which uses ES module syntax so while the node.js doesn't support fully this syntax it seems to be unsolvable. I see that setting type:module in the ckeditor5-angular/package.json should solve the issue for node>14.x.x. - https://nodejs.org/api/esm.html#esm_enabling.

@dinesh-rawat, could you test it and tell whether it fixes the issue?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ninadh26 picture ninadh26  Â·  6Comments

Ruud-cb picture Ruud-cb  Â·  10Comments

Karman40 picture Karman40  Â·  5Comments

maximelafarie picture maximelafarie  Â·  4Comments

ma2ciek picture ma2ciek  Â·  9Comments