First, let's take a look at some basics without Angular. For CKEditor version 4, we can initialize an editor with the filebrowserImageUploadUrl
configuration option, which enables functionality from the File Browser API:
CKEDITOR.replace('editor', {
filebrowserImageUploadUrl: '/upload.php?type=image'
});
This just loads an editor instance onto a <textarea name="editor">
. Because we set the filebrowserImageUploadUrl
option, the Upload tab becomes available in the editor's image dialog. The example value, /upload.php?type=image
, is the URL to the PHP script on the server that handles the uploaded image files.
When a user uploads an image, CKEditor will send the image to this URL on the server. The handler at this URL should validate the request, resize the image (if needed), and move the uploaded image to a permanent location on the server. Then, the handler sends an HTML response back to CKEditor with the image's public URL.
Of course, we can write the server-side handler in any language. Here's a basic example for PHP that we'll save as upload.php:
<?php
$tempName = $_FILES['upload']['tmp_name'];
$fileName = uniqid() . $_FILES['upload']['name'];
$uploadPath = '/path/to/uploads/' . $fileName;
$imageUrl = 'http://example.com/uploads/' . $fileName;
$success = move_uploaded_file($tempName, $uploadPath);
$html = '<script>window.parent.CKEDITOR.tools.callFunction(%s, "%s", "%s");</script>';
$message = $success ? 'Uploaded successfully.' : 'Upload failed.';
echo sprintf($html, $_GET['CKEditorFuncNum'], $imageUrl, $message);
This script places an uploaded image into the web server's uploads/ directory so the browser can fetch the image. It passes back the CKEditorFuncNum
parameter from the request to identify the appropriate callback for the upload. This example provides some basic protection against duplicate filenames, but, for a real-world application, we'd need to add security, validation, and error handling (authentication, CSRF, file type checking, max size, file name sanitization, etc.).
So far, this all works with CKEditor's standard, built-in functionality (no plugins, Angular, or jQuery needed). To enable users to drag-and-drop or paste images into the editor, we can add the Upload Image plugin to our CKEditor build (or use the standard-all distribution from the CKEditor CDN).
We need to declare the plugin when initializing the editor:
CKEDITOR.replace('editor', {
extraPlugins: 'uploadimage',
filebrowserImageUploadUrl: '/upload.php?type=image'
});
...and then extend our upload.php script to return the JSON response expected by the plugin. Add this block before the last three lines of the previous example:
if (isset($_GET['responseType']) && $_GET['responseType'] === 'json') {
echo json_encode([
'uploaded' => $success,
'fileName' => $fileName,
'url' => $imageUrl,
]);
return;
}
The Upload Image plugin sends the responseType=json
URL parameter that the server-side script can check for to determine which type of response to send back.
Finally, let's take a look at how to initialize an editor using the angular-ckeditor package described in the question:
<div ng-controller="EditorCtrl as editor">
<textarea ckeditor="editor.options" ng-model="editor.content"></textarea>
</div>
var myApp = angular.module('myApp', ['ckeditor'])
myApp.controller('EditorCtrl', function () {
this.options = {
extraPlugins: 'uploadimage',
filebrowserImageUploadUrl: '/image-upload.php?type=image'
};
});
As we can see, we don't need to do much to "angularize" this. Once we create our template, we declare the same configuration options that we'd pass to the plain CKEDITOR.replace()
on a controller that we reference on an element with the ckeditor
directive.