Business central blog
Subscribe to blog and get news about new posts.

Summernote WYSIWYG. Free Business Central rich text editor. New app updates.

One of the frequent requests I hear from users is the WYSIWYG editor. Unfortunately, Microsoft has not added the editor yet. So I decided to integrate some free editor into Business Central. My choice was summernote, a simple and functional WYSIWYG editor. I will also talk about new app updates.


In short, WYSIWYG is an application for easy editing and displaying a variety of content. There is a huge variety of these editors, both paid and free. I did a little analysis and my personal choice was summernote. It is absolutely free, constantly updated and easy to use. Note that the most popular and powerful editor is TinyMCE, but it is not entirely free and depends on API key.
Summernote documentation is very simple and the main part fits on half a page:
Following the documentation, create a ControlAddIn in which we specify which scripts and style sheets should be loaded. Here, by the way, the order is important: first we load the jQuery library, then Bootstrap (since summernote is written on it), and then summernote itself.
Apart from that, I have declared some functions. In addition to the standard ControlAddinReady event, which is triggered when ControlAddIn is loaded, I added OnChange(Data: Text), which should be triggered when we change something in the editor window.
Let's look at the main function that initiates the summernote WYSIWYG with the text that comes in the Data parameter. I tried to leave more comments in the code to make it clearer what was going on.

function InitializeSummerNote(Data) {
    //Initialize editor only once when DOM is loaded
    $(document).ready(function() {
        //Bind InvokeExtensibilityMethod for OnChange BC event
        const OnChange = getALMethod('OnChange',false);
        editor = $('#summernote');
            height: ($(window).height() - 55),
            focus: true,
            callbacks: {
                //Bind onChange callback with our OnChange BC event
                onChange: function(contents, $editable) {
            //List of features to include them to toolbar
            toolbar: [
                ['style', ['style']],
                ['font', ['bold', 'underline', 'clear']],
                ['fontname', ['fontname']],
                ['color', ['color']],
                ['para', ['ul', 'ol', 'paragraph']],
                ['table', ['table']],
                ['insert', ['link', 'picture', 'video']],
                ['view', ['codeview', 'help']],
        //Set init data
I would like to note the two most important points. First, for those who are not familiar with CallBacks, it may seem that onChange is triggered only once, but in fact this method will be executed every time onChange is triggered in the summernote itself. Second, getALMethod('OnChange',false); is actually the familiar Microsoft.Dynamics.NAV.InvokeExtensibilityMethod that is used to call a specific trigger on the ControlAddin page.The main difference from a direct call is that we use the additional parameter CallBack to wait for the previous AL events to work and only then call the current event. This is a function I picked up from Vjeko. I strongly advise you to read his article about it.
Now the easiest thing is to add usercontrol ControlAddin to the page. Once ControlAddinReady we initialize the summernote editor by passing the content as text through the Rec.GetContent() function. In the same way, every time we change the content inside the summernote it's called OnChange(Data: Text) and we save it to the database via Rec.SetContent(Data) method OnClosePage trigger.

page 81500 "SMT Summer Note Editor"
    Caption = 'Summer Note Editor';
    PageType = Card;
    UsageCategory = None;
    SourceTable = "SMT Content";

                Caption = 'Editor';
                usercontrol(SMTEditor; "SMT Editor")
                    ApplicationArea = All;
                    trigger ControlAddinReady()
                        NewData := Rec.GetContent();

                    trigger OnChange(Data: Text)
                        NewData := Data;

    trigger OnNewRecord(BelowxRec: Boolean)
        if Rec.GetFilter("Source Record ID") <> '' then
            evaluate(Rec."Source Record ID", Rec.GetFilter("Source Record ID"));

    trigger OnClosePage()

        NewData: Text;
An "HTML Content" action has been aded to Sales and Purchase order pages which allow you to open a list of content specific to the selected order.
In addition, if you have uploaded a Document Attachment in html format, you can view and edit it with the new "Edit HTML" action:
I will not talk about the possibilities, because they are more or less standard. I advise you to install and try it yourself. Or you can test it on their homepage Enjoy!
I've also updated PDF.js, so now you have the ability to view the contents of the PDF in Document Attachments without downloading the file:
Now you can filter the list of fields before loading the tables:
May 30, 2022