I am looking for an example showing an implementation of custom image uploader for CKEditor 5 using Angular 5.
I got this to work with relatively little fuss. It does not require rebuilding CKEditor. Here are the basic steps:
In your component, define an instance variable with a CKEditor configuration object if you have not already done so. It needs to have an extraPlugins element in it:
ckconfig = {
// include any other configuration you want
extraPlugins: [ this.TheUploadAdapterPlugin ]
};
Step two create the referenced function in your component that looks like this:
TheUploadAdapterPlugin(editor) {
console.log('TheUploadAdapterPlugin called');
editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
return new UploadAdapter(loader, '/image');
};
}
Step three create the new class that was referenced in the above function. You can do this in the same Typescript file after the component definition or you can make it in a separate file and import it.
class UploadAdapter {
loader; // your adapter communicates to CKEditor through this
url;
constructor(loader, url) {
this.loader = loader;
this.url = url;
console.log('Upload Adapter Constructor', this.loader, this.url);
}
upload() {
return new Promise((resolve, reject) => {
console.log('UploadAdapter upload called', this.loader, this.url);
console.log('the file we got was', this.loader.file);
resolve({ default: 'http://localhost:8080/image/1359' });
});
}
abort() {
console.log('UploadAdapter abort');
}
At the quick testing stage change the resolve call to return a URL that points to some fixed image. It can be anything. That URL string will be stuck into the editor content where user places the image.
When you go to implement, you will delete or change each of the console.log calls to whatever logic you want -- likely involving some calls to Angular's HttpClient. However note that the functions will execute outside of Angular's NgZone domain.
Your logic in resolve will have to generate the appropriate URL of course. Check the CKEditor documentation for a good example of how to interact with the loader.
Finally you need to make sure your ckeditor element is using the ckconfig configuration object something like this:
<ckeditor [editor]="Editor" [config]="ckconfig"
[(ngModel)]="doc.text" name="editcontent"></ckeditor>
Now when you use this editor you will use the tool to upload an image. You should see the output on the console log and the string in the resolve call inserted into the editor's content. If the string is a valid URL to an image somewhere you will see that image.
If this works for you there should be little problem completing the plug in.
Remember the generated Promise has a reject parameter so use it as needed.
There's no need for the Angular-specific version of that adapter.
You can use for example this: https://github.com/pourquoi/ckeditor5-simple-upload or try to integrate it with the CKFinder.
Then, all you need to do is to pass the configuration object to the <ckeditor [config]='config'>
component. Don't forget to set allowJs: true
in your tsconfig.json
file to allow bundling local JS files.
Alternatively, you can create it on your own. This should be the base skeleton of the upload adapter that should match the UploadAdapter interface:
editor.plugins.get( 'FileRepository' ).createUploadAdapter = loader => {
return new UploadAdapter( loader, editor.config.get( 'uploadUrl' ), editor.t );
}
class UploadAdapter {
constructor( loader, url, t ) {
this.t = t; // Translate function
this.loader = loader;
this.url = url; // Endpoint URL
}
upload() {
// Perform uploading and return a promise to that action.
}
abort() {
// Abort current upload process.
}
}
The whole process is described more deeply in docs: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/deep-dive/upload-adapter.html. You can also look at the source code of https://github.com/pourquoi/ckeditor5-simple-upload/blob/master/src/adapter.js
Then, to get the editor
property in the ckeditor5-angular
package you need to do listen to the ready
event and obtain the editor parameter:
<editor [ready]="onReady" ...></editor>
@Component()
class EditorComponent {
public onReady( editor ) {
// Now you can acess the editor.
}
}
And that's besically it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With