Reputation: 806
This question may have already answers but none of them is Angular specific. Here are some of them
I am using Angular 5 and following this documentation to implement ckeditor5-angular.
But I am having issue with image uploading, when I try uploading image it says in the browser console.
filerepository-no-upload-adapter: Upload adapter is not defined. Read more: https://docs.ckeditor.com/ckeditor5/latest/framework/guides/support/error-codes.html#error-filerepository-no-upload-adapter
I have tried searching for this issue and was able to find a lot of solutions, but literally I couldn't understand a single of them because they were not Angular specific.
Please help how can I upload image.
Upvotes: 11
Views: 19486
Reputation: 367
Try this out for Angular
You can either choose to use base64 or upload the file to your server and return the file url
///component.ts
onReady(editor: any): void {
editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader: any ) => {
return new ckeditor5UploadAdapter( loader, this.apiService);
};
}
Full code to upload to server and get the file url
this option will make your content more clean and prevent storage all content images in your db
//adapterClass.ts
import { ApiService } from "src/app/app-services/api.service";
import { environment } from "src/environment/environment"
export class ckeditor5UploadAdapter {
constructor(private loader: any, private apiService: ApiService) { }
public upload() {
return new Promise((resolve, reject) => {
this.loader.file.then((file: File) => {
const reader = new FileReader();
reader.onload = async (e: any) => {
const imageurl = await this.getImageLink(e.target.result);
resolve({ default: environment.appUrl + '/storage/' + imageurl });
};
reader.readAsDataURL(file);
});
})
}
getImageLink(base64Img: string) {
return new Promise((resolve, reject) => {
this.apiService.post('admin/image/upload', { base64Img })
.subscribe(response => {
if (response.status === "success") {
resolve(response.imageLink);
} else {
resolve("");
}
});
})
}
abort() {
console.error('aborted');
}
}
to return base64 image(no need in storing file in server), replace this code
reader.onload = async (e: any) => {
const imageurl = await this.getImageLink(e.target.result);
resolve({ default: environment.appUrl + '/storage/' + imageurl });
};
with this
reader.onload = async (e: any) => {
resolve({ default: e.target.result});
};
Upvotes: 0
Reputation: 385
Thank you for everyone answer. I create code snippet for anyone who want looking the example. But I used ckeditor inline build. Hope it help.
Upvotes: 3
Reputation: 870
In component.html
file add following code
<ckeditor [editor]="Editor" (ready)="onReady($event)"></ckeditor>
in component.ts
file create function onReady(data)
onReady(eventData) {
eventData.plugins.get('FileRepository').createUploadAdapter = function (loader) {
console.log(btoa(loader.file));
return new UploadAdapter(loader);
};
}
Add new class called UploadAdapter
and add following code:-
export class UploadAdapter {
private loader;
constructor(loader: any) {
this.loader = loader;
console.log(this.readThis(loader.file));
}
public upload(): Promise<any> {
//"data:image/png;base64,"+ btoa(binaryString)
return this.readThis(this.loader.file);
}
readThis(file: File): Promise<any> {
console.log(file)
let imagePromise: Promise<any> = new Promise((resolve, reject) => {
var myReader: FileReader = new FileReader();
myReader.onloadend = (e) => {
let image = myReader.result;
console.log(image);
return { default: "data:image/png;base64," + image };
resolve();
}
myReader.readAsDataURL(file);
});
return imagePromise;
}
}
here default
indicate uploaded image url. I have converted file in base64 but you can call server url and upload your file then return server url with same key.
EnjOy CodInG :)
Upvotes: 13
Reputation: 140
I solved this by implementing my own UploadAdapter
if you use Editor.create()
,that would create a new editor element, not associate with the angular component
<ckeditor
[editor]="Editor"
[(ngModel)]="content"
(ready)="onReady($event)"
>
</ckeditor>
at component.ts
onReady($event){
$event.plugins.get('FileRepository').createUploadAdapter = (loader)=> {
return new UploadAdapter(loader,'',this.http);
};
}
UploadAdapter.ts
import { HttpParams, HttpClient } from "@angular/common/http";
export class UploadAdapter {
constructor(
private loader,
public url:string,
private http:HttpClient
) {
}
//the uploadFile method use to upload image to your server
uploadFile(file,url?:string,user?:string){
let name = '';
url='your api';
let formData:FormData = new FormData();
let headers = new Headers();
name = file.name;
formData.append('attachment', file, name);
const dotIndex = name.lastIndexOf('.');
const fileName = dotIndex>0?name.substring(0,dotIndex):name;
formData.append('name', fileName);
formData.append('source', user);
headers.append('Content-Type', 'multipart/form-data');
headers.append('Accept', 'application/json');
console.log('formData',formData);
let params = new HttpParams();
const options = {
params: params,
reportProgress: true,
};
//http post return an observer
//so I need to convert to Promise
return this.http.post(url,formData,options);
}
//implement the upload
upload() {
let upload = new Promise((resolve, reject)=>{
this.loader['file'].then(
(data)=>{
this.uploadFile(data,this.url,'test')
.subscribe(
(result)=>{
//resolve data formate must like this
//if **default** is missing, you will get an error
**resolve({ default: result['attachment'] })**
},
(error)=>{
reject(data.msg);
}
);
}
);
});
return upload;
}
abort() {
console.log("abort")
}
}
Upvotes: 4
Reputation: 11
I was trying to use zackhalil's solution. The image was displayed in the editor, but when I get the value to update the database, I just have:
<figure class="image"><img></figure>
To fix this, I changed the following code:
return { default: "data:image/png;base64," + image };
resolve();
to:
resolve({ default: image });
Upvotes: 0
Reputation: 533
I used the below seems to work
class UploadAdapter {
constructor( loader ) {
this.loader = loader;
}
upload() {
return this.loader.file
.then( file => new Promise( ( resolve, reject ) => {
var myReader= new FileReader();
myReader.onloadend = (e) => {
resolve({ default: myReader.result });
}
myReader.readAsDataURL(file);
} ) );
};
}
Upvotes: 7