First thing, it seem this issue uses another packages: https://github.com/ckeditor/ckeditor5-angular/issues/88
Packages i install:
ckeditor5-
adapter-ckfinder
angular
build-classic
build-decoupled-document
ckfinder
core
editor-decoupled
engine
ui
upload
utils
in the upload i found: base64uploadadapter.js
Another thing... i have no idea how config work, how to add simple plugin, how to manythings, how js based sample can be converted to angular.
Here's my code:
import { Component, OnInit } from '@angular/core';
import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import * as DecoupledEditor from '@ckeditor/ckeditor5-build-decoupled-document';
import Base64UploadAdapter from '@ckeditor/ckeditor5-upload/src/base64uploadadapter';
import { FormBuilder, Validators, FormGroup, ValidationErrors } from '@angular/forms';
import { Util } from 'leaflet';
import { environment } from 'src/environments/environment';
import { Utility } from 'src/_utility/Utility';
@Component({
selector: 'app-story-insert',
templateUrl: './story-insert.component.html',
styleUrls: ['./story-insert.component.less']
})
export class StoryInsertComponent implements OnInit {
util = Util;
public ckEditor = DecoupledEditor; // ClassicEditor;
insertForm: FormGroup;
envValidators = environment.validations;
public onReady( editor ) {
editor.ui.getEditableElement().parentElement.insertBefore(
editor.ui.view.toolbar.element,
editor.ui.getEditableElement()
);
// tslint:disable-next-line:max-line-length
// Only useful source: https://stackoverflow.com/questions/52052514/upload-adapter-is-not-defined-issue-with-image-uploading-in-ckeditor5-angular/55237874#55237874
editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
console.log(btoa(loader.file));
return new Base64UploadAdapter(loader); // UploadAdapter(loader);
};
}
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.insertForm = this.fb.group({
title: ['', [Validators.required, Validators.maxLength(this.envValidators.titleMaxLength)]],
description: ['', [Validators.required, Validators.maxLength(this.envValidators.descriptionMaxLength)]],
keywords: ['', [Validators.required, Validators.maxLength(this.envValidators.articleKeywordMaxLength)]],
articleContent: ['']
}, {
validators: [this.ckEditorArticleValidator('articleContent')]
});
}
public ckEditorArticleValidator(ckEditorField: string): (g: FormGroup) => ValidationErrors | null {
const validator = (g: FormGroup): ValidationErrors | null => {
const ckEditorCtrl = g.get(ckEditorField);
if (Utility.isNullOrUndefinedOrWhiteSpace(ckEditorCtrl.value)) {
return {ckeditor_required: true};
} else if (ckEditorCtrl.value.length > 4000) {
return {ckeditor_maxlength: true};
}
return null;
};
return validator;
}
insertStory(): void {
}
get title() {
return this.insertForm && this.insertForm.get('title');
}
get description() {
return this.insertForm && this.insertForm.get('description');
}
get keywords() {
return this.insertForm && this.insertForm.get('keywords');
}
get articleContent() {
return this.insertForm && this.insertForm.get('articleContent');
}
}
I get this error:
log.js:58 ckeditor-duplicated-modules: Some CKEditor 5 modules are duplicated. Read more: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html#error-ckeditor-duplicated-modules
undefined
After click and upload image, i get this error:
TypeError: this._adapter.upload is not a function
~If you want to add plugins to the editor, you should create a custom build, then import it to your project instead of ckeditor5-build-classic. Please, see our~ ~Installing plugins guide~~.~
Update:
The easiest way to set the upload adapter or to add / remove plugin from the build is by creating a custom build via the CKEditor 5 Online Builder that includes your own set of plugins. Then, you should follow the CKEditor 5 Angular integration - custom build section.
The issue i have is i'm using angular, and i do not know how to perform these configurations inside angular. and no page about it.... also
was this right thing to do?
// tslint:disable-next-line:max-line-length
// Only useful source: https://stackoverflow.com/questions/52052514/upload-adapter-is-not-defined-issue-with-image-uploading-in-ckeditor5-angular/55237874#55237874
editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
console.log(btoa(loader.file));
return new Base64UploadAdapter(loader); // UploadAdapter(loader);
};
Are my errors because i use decoupled-document ? isn't that a custom build?
The docs for the Base64 image upload adapter are available here: https://ckeditor.com/docs/ckeditor5/latest/features/image-upload/base64-upload-adapter.html.
So you should add this plugin to the array of plugins instead of manually setting the upload adapter like this: editor.plugins.get('FileRepository').createUploadAdapter....
But the other thing is what @Mgsy noted, you shouldn't add a plugin to the existing build (because of module duplication, PostCSS errors, invalid instanceof checks and so on...) and you should create a build using the https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/installing-plugins.html guide. Then with this customized build, you should have the upload adapter already customized.
If you don't want to rebuild CKEditor5 every release, then you can set:
editor.plugins.get( FileRepository ).createUploadAdapter = loader => new Adapter( loader );
and copy the base64 Adapter definition (https://github.com/ckeditor/ckeditor5-upload/blob/master/src/adapters/base64uploadadapter.js#L56-L108).
Feel free to ask any questions.
Hi, sorry, my answer was a bit imprecise.
Using ClassicEditor, is the base64 image plugin included?
No, it's present in the ckeditor5-upload package, but the ClassicEditor build doesn't ship it by default. That's why you need to customize the build or add your own plugin to the existing build.
Where does someone write this
editor.plugins.get( FileRepository ).createUploadAdapter = loader => new Adapter( loader );
Here goes a sample implementation:
<ckeditor (ready)="onReady($event)"...>
@Component(...)
export class MyEditor {
onReady( editor ) {
editor.plugins.get( 'FileRepository' ).createUploadAdapter = loader => new Adapter( loader );
}
}
class Adapter {
// Use https://github.com/ckeditor/ckeditor5-upload/blob/78424289e89834d3e3b722523e3c326acde925e5/src/adapters/base64uploadadapter.js#L56-L108
}
Where does Adapter come from?
Like I mentioned in the previous post the implementation can be similar to the https://github.com/ckeditor/ckeditor5-upload/blob/78424289e89834d3e3b722523e3c326acde925e5/src/adapters/base64uploadadapter.js#L56-L108
How do I this Base64UploadAdapter without getting the duplicate modules error?
Following the above steps, you won't get this message because you won't duplicate CKEditor 5 packages.
why do i have to clone your code and do a custom build just to add that plugin... this is ridiculous...
edit: ok i just copy pasted your code into my project... just 1 hour with your library and i already want to throw it and do it myself. why such complexity? i don't want to read your doc totally before starting to work... that's not how it works in 2020. in 2020 the getting start guide should be enough to cover 90% of the cases. then if the library is great we go deep to the doc, to customize as we want. i just started to read your doc and i already want to give up. "in order to do a simple thing start cloning our code first" why?! "read our 5000 pages of doc to understand how our textarea works" ... you don't like developers dude. you are just like the people who created so many bad games on NES and master system when we were kids, just to make us suffer for nothing.
why do i have to clone your code and do a custom build just to add that plugin... this is ridiculous...
edit: ok i just copy pasted your code into my project... just 1 hour with your library and i already want to throw it and do it myself. why such complexity? i don't want to read your doc totally before starting to work... that's not how it works in 2020. in 2020 the getting start guide should be enough to cover 90% of the cases. then if the library is great we go deep to the doc, to customize as we want. i just started to read your doc and i already want to give up. "in order to do a simple thing start cloning our code first" why?! "read our 5000 pages of doc to understand how our textarea works" ... you don't like developers dude. you are just like the people who created so many bad games on NES and master system when we were kids, just to make us suffer for nothing.
I'll hide my previous response as it's outdated a little bit. Use CKEditor 5 Online builder instead.
I updated the solution - https://github.com/ckeditor/ckeditor5-angular/issues/126#issuecomment-515977433.
Thank you for the quick reply. I switched to quill, and it works as I want so far (base64 images out of the box):

Also the buttons are responsive out of the box( had an issue with that with ckEditor 5 ):

I understand your reasons but imo it should be different. First of all, I took the "Document" build, and the upload image icon is there by default in the toolbox. So I imagine that the plugin should be there as well.
I'm a backend developer, so I'm not an expert with webpack, I have to admit it. But for other libraries, I'm used to do stuff like:
npm install @ckEditor/angular-plugin-file-base-64
then in my imports: ImageBase64Module.
That makes more sense imo. I will have a look to the online builder, but I don't like this solution, because then I have to manage your project somewhere on a git repo. This would produce issue:
-> how do I align my version with the default one, in case of bug fixing for instance?
Another solution would be to define interfaces that we can implement. I couldn't find an interface like "Plugin" in the document build, althought it would be very useful. Then I know what's expected from the plugin management system.
The toolbar for each build should be minimalistic if you don't bundle the according plugins, at least a default one. Because we think if it's there, then it's part of the build. but it's not.
Thanks for the reply again, CkEditor looks like a great product, but for proof of concept like I'm doing now, it doesn't fit. Developer experience can definitely be improved.
Thanks for the feedback!
I understand your reasons but imo it should be different. First of all, I took the "Document" build, and the upload image icon is there by default in the toolbox. So I imagine that the plugin should be there as well
The plugin for handling image inside the editor is built-in to all builds. However the "upload" part which requires the Image plugin can be defined in various ways. Thus why there's an image button, but there's no image adapter set. Actually, the base64 could be the default one, but uploading a few images would blow up your data and while it makes sense for PoCs it doesn't make sense for larger apps.
I'm a backend developer, so I'm not an expert with webpack, I have to admit it. But for other libraries, I'm used to do stuff like:
npm install ckEditor/angular-plugin-file-base-64
Yes... It works this way in our React and Vue integrations. But because of the mentioned issue with Angular loaders incompatibility and no way to configure the webpack for the Angular's app there's currently no way to do that. I know it's a big pain. But the CKEditor 5 wasn't developed for Angular ecosystem. It's a pure Vanilla JS editor. Unfortunately, we added two loaders needed to compile our sources - SVG loader and (Post)CSS loaders to not write everything in the JS files and to be able to reuse some parts of the UI, plus be able to configure the output. That's actually a bit PITA in the JS ecosystem. There're many "standards" that are conflicting. with only one default loader for CSS and SVG that problem wouldn't exist.
That makes more sense imo. I will have a look to the online builder, but I don't like this solution, because then I have to manage your project somewhere on a git repo. This would produce issue:
-> how do I align my version with the default one, in case of bug fixing for instance?
There're a few tools like `npm-check-updates` and similar ones which can update picked dependencies to latest ones. We'll also provide a tool to download an updated version of your packages from the CKEditor 5 Online Builder tool.
Another solution would be to define interfaces that we can implement. I couldn't find an interface like "Plugin" in the document build, althought it would be very useful. Then I know what's expected from the plugin management system.
Have you seen the https://ckeditor.com/docs/ckeditor5/latest/framework/guides/creating-simple-plugin.html and Plugin interface? There's also the Plugin base class, which you can use to inherit some useful methods from it.
Thanks for the reply again, CkEditor looks like a great product, but for proof of concept like I'm doing now, it doesn't fit. Developer experience can definitely be improved.
I think that the core of the problem is that it doesn't work out of the box. But there're a few reasons why it currently behaves differently.
Also the buttons are responsive out of the box( had an issue with that with ckEditor 5 ):
Could you tell more about it? And could you create an issues in the CKEditor 5 issue tracker?
Hey,
Sorry I didn't create a issue on github because I didn't go further but here it is:

As you see, the toolbar goes outside the window in case of mobile device; maybe it's not a bug, I am not sure; also there is no borders on the textarea part;
Step to reproduce:
npm install --save @ckeditor/ckeditor5-angular
npm i @ckeditor/ckeditor5-build-decoupled-document
app.module.ts:
imports: [
...,
CKEditorModule
]
document.component.ts:
public Editor = DecoupledEditor;
public onReady( editor ) {
editor.ui.getEditableElement().parentElement.insertBefore(
editor.ui.view.toolbar.element,
editor.ui.getEditableElement()
);
}
document.component.html:
<ckeditor [editor]="Editor" data="<p>Hello, world!</p>" (ready)="onReady($event)"></ckeditor>
if you confirm it's a bug i'll create a ticket np, btw it is the hello world example, i didn't try to customize anything
For the base64 images I can live with it because I'm storing the document as an html page on the disk (server side), I just have a reference to the file in the database (mongodb); I could use GridFS to store it with mongo but I was too lazy yesterday haha. Also I don't think the document will contains tons of images, so I can live with my solution. For the Plugin interface, I couldn't find it in the npm packages I've installed (same as the hello world example), I think I had to make a custom build anyway to get that interface; Managing an external dependency is not something I did often during my carreer , 7y doing backend dev. I did it two times yes, it wasn't my idea and i didn't like it (and we end up having issues with that). I see external deps as black boxes. Having it on a private repo means that if a developer starts working on my project, he has to clone two projects and not one. or I could have my own npm registry, but all those steps equals less productive work imo. I'll try it again once my POC is over, lots of nice plugins there, maybe i'll switch to react or vue (the nice thing when being backend dev is to be completely open for changes on the frontend framework :D i like vuejs for its simplicity, maybe the experience will be better with it)
I assume people are still ending up here trying to figure out how to integrate this all into an Angular Application, specifically with the simpleFileUpload plugin. I made a sample repo of this being done using the custom build tool CKEditor offers and added the steps in the README, cheers!
Getting this error when using online builder to build with custom plugins.
core.js:5980 ERROR Error: Uncaught (in promise): CKEditorError: ckeditor-duplicated-modules
Read more: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html#error-ckeditor-duplicated-modules
CKEditorError: ckeditor-duplicated-modules
Read more: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html#error-ckeditor-duplicated-modules
at Object.<anonymous> (ckeditor.js:5)
at Object.push.+z1p (ckeditor.js:5)
at n (ckeditor.js:5)
at Module.<anonymous> (ckeditor.js:5)
at n (ckeditor.js:5)
at push.+z1p (ckeditor.js:5)
at ckeditor.js:5
at ckeditor.js:5
at Object.+z1p (ckeditor.js:5)
at __webpack_require__ (bootstrap:84)
at resolvePromise (zone-evergreen.js:798)
at resolvePromise (zone-evergreen.js:750)
at zone-evergreen.js:860
at ZoneDelegate.invokeTask (zone-evergreen.js:399)
at Object.onInvokeTask (core.js:28289)
at ZoneDelegate.invokeTask (zone-evergreen.js:398)
at Zone.runTask (zone-evergreen.js:167)
at drainMicroTaskQueue (zone-evergreen.js:569)
@ma2ciek
I followed @ecolara3 instruction and hit a brick wall.
the issue is that the custom build tool for ckeditor 5 (https://ckeditor.com/ckeditor-5/online-builder/) results in an ES6 build.
according to: https://github.com/ckeditor/ckeditor5-angular/issues/20 this ES6 build is using some uglifier resulted in throwing compilation error root is undefined for angular projects.
Please add ES5 build option to the custom build tool.
it's already a huge among of pain to customize ckeditor 5 for angular, please do not make it even worse.
Most helpful comment
why do i have to clone your code and do a custom build just to add that plugin... this is ridiculous...
edit: ok i just copy pasted your code into my project... just 1 hour with your library and i already want to throw it and do it myself. why such complexity? i don't want to read your doc totally before starting to work... that's not how it works in 2020. in 2020 the getting start guide should be enough to cover 90% of the cases. then if the library is great we go deep to the doc, to customize as we want. i just started to read your doc and i already want to give up. "in order to do a simple thing start cloning our code first" why?! "read our 5000 pages of doc to understand how our textarea works" ... you don't like developers dude. you are just like the people who created so many bad games on NES and master system when we were kids, just to make us suffer for nothing.