Implement Custom Image Handler In SPFx Rich Text Editor Using Angular 4

In my previous article, I described how to integrate Rich Text Editor in SharePoint Framework (SPFx) Angular webparts. Now, let’s see how do we implement custom image handler in the same. So, you are able to save the images uploaded in Rich Text Editor to the desired destination folder.

Let’s directly go to the implementation with the below steps.

Get the ngx-quill editor instance.

Once the editor is created/rendered in our View, we will need to get the ngx-quill editor instance. It will be helpful to add our custom handlers to the controls in the editor or even you could add your own custom controls.

Use the onEditorCreated event to get the editor instance. Please find the below code snippet.

Component HTML file.

  1. <quill-editor [(ngModel)]="DescriptionHF" (onEditorCreated)="editorCreated($event)">  
  2. </quill-editor> 

Component.ts file

  1. private editorInstance: any;  
  2. private editorCreated(quill: any) {  
  3.     this.editorInstance = quill;  
  4.     var toolbar = this.editorInstance.getModule('toolbar');  
  5.     toolbar.addHandler('image'this.imageEditorHandler.bind(this));  

This event will be raised once the editor is created in the page, so we will have access to the toolbar of the Quill Editor. In the second line of the method, we get the toolbar module in the variable toolbar. Image control name in the quill toolbar is image. In the toolbar instance, we do have a method to add handlers.

The last line of code in the above method demonstrates how to register the custom image handler in quill-editor toolbar.

How to get current page context in the quill editor handler method?

If you notice in the above method, highlighted content bind(this) will get you the current page context inside the handler whenever an image icon is clicked in the quill editor toolbar.

How to insert the selected image in quill editor using image handler?

Once we are into the handler method the first thing we need to do is to get the selection range, i.e, to get the cursor range so we could insert the image where the cursor points to. To get the range of index use the below line of code in the handler,

  1. const range = this.editorInstance.getSelection(); 

Now, let’s pop up the image selection window using the default image control in the HTML. Create image control dynamically inside the handler and use its change event to process the selected image.

Please find the below handler method with all the functionalities,

  1. private imageEditorHandler() {  
  2.     if (this.editorInstance != null)) {  
  3.     const range = this.editorInstance.getSelection();  
  4.     if (range != null) {  
  5.         let input = document.createElement('input');  
  6.         input.setAttribute('type''file');  
  7.         input.setAttribute('accept''image/*');  
  8.         input.addEventListener('change', () => {  
  9.             if (input.files != null) {  
  10.                 let file = input.files[0];  
  11.                 if (file != null) {  
  12.                     var reader = new FileReader();  
  13.                     reader.readAsDataURL(file);  
  14.                     reader.onerror = function(error) {  
  15.                         console.log('Error: ', error);  
  16.                     };  
  17.                     reader.onloadend = function() {  
  18.                         //Read complete  
  19.                         if (reader.readyState == 2) {  
  20.                             var base64result = reader.result;  
  21.                             //Write your code to upload image in your custom location  
  22.                         }  
  23.                     };  
  24.                 }  
  25.             }  
  26.         });  
  27.         input.click();  
  28.     }  
  29. }  
  30. }  

The change event listener should be registered before clicking the dynamically created file control.

We will be using FileReader to read the file and convert it into a base64 string and in the above code snippet, we got base64String in the variable base64result.

Once we got the base64string you can insert the image in the editor by using the insertEmbed method of quill editor instance like below,

  1. this.editorInstance.insertEmbed(range.index, 'image', base64result);  

In the above line, if you notice, there is range.index which is used to insert the image at the appropriate location in the editor.

How to save the image in a library in SPFx?

SharePoint provides a lot of REST API endpoints which could be helpful to manipulate data in SharePoint.

The following blog posts will help you for sure in detail about handling Lists and Groups in SPFx.

Now, let’s see how to upload image to SharePoint from SPFx using REST API.

Method - POST

URL
{ReplaceYourSiteUrl}//_api/web/GetFolderByServerRelativeUrl('{ServerRelativeUrlOfFolder}')/Files/add(url='{FileName}',overwrite=true)

  1. let requestUrl = currentWebUrl.concat(“/_api/web / GetFolderByServerRelativeUrl('{ServerRelativeUrlOfFolder}') / Files / add(url = '{FileName}', overwrite = true)”);  
  2. let spOpts = {  
  3.     headers: {  
  4.         "Accept""application/json;",  
  5.         "Content-Type""multipart/form-data",  
  6.         'Content-Length'""  
  7.     },  
  8.     body: FileObject  
  9. };  
  10. this.context.spHttpClient.post(requestUrl, SPHttpClient.configurations.v1, spOpts);  

The beauty of this code is that you have no need to pass the base64 to this API. You can directly pass the FileObject selected from the file control. Since we are mentioning content-type as multipart/form-data in API Request, SharePoint will handle it for you.

This article described just a sample about integrating the custom image handler in ngx-quill editor and how to insert it in the cursor point position and upload it at the desired location in SharePoint.

If you have any questions/issues about this article, please let me know in the comments.