Control multiple RTE with a single ribbon

Is it possible to control multiple text editors with a single ribbon?

I want to create a form with multiple inputs that should have RTE options (like bold, italic etc.) but have a single ribbon on top of the page for the user to control them with.


4 Replies

VY Vinothkumar Yuvaraj Syncfusion Team August 19, 2024 03:54 PM UTC

Hi Ivaylo Dimitrov,


We have validated your query and created a sample where we control the Rich Text Editor using the Ribbon component. In the sample, we retrieve the Rich Text Editor instance during the focus event. When a ribbon item such as bold, italic, etc., is clicked, we use the executeCommand method to apply the formatting to the content of the focused editor. Please see the following code and sample for your reference.


index.js

const Default = () => {

    let rteObj;

    const toolbarSettings = {

        enable: false

    }

    function tabSelecting(e) {

        if (rteObj != null) {

            switch (e) {

                case "Bold":

                    rteObj.executeCommand('bold',null,{ undo: true });

                    break;

                case "Italic":

                    rteObj.executeCommand('italic',null,{ undo: true });

                    break;

                case "Underline":

                    rteObj.executeCommand('underline',null,{ undo: true });

                    break;

                case "Strikethrough":

                    rteObj.executeCommand('strikeThrough',null,{ undo: true });

                    break;

            }

        }

    }

    function focus(e) {

        rteObj = e.event.currentTarget.ej2_instances[0];

    }

    return (<div className='control-pane'>

        <div>Ribbon Component</div>

        <RibbonComponent id="ribbon" >

            <RibbonTabsDirective>

                <RibbonTabDirective header="Home">

                    <RibbonGroupsDirective>

                        <RibbonGroupDirective header="editor" orientation="Row">

                            <RibbonCollectionsDirective>

                                <RibbonCollectionDirective>

                                    <RibbonItemsDirective>

                                        <RibbonItemDirective type="Button" allowedSizes={RibbonItemSize.Small} buttonSettings={{ iconCss: "e-icons e-bold", content: "Bold", clicked: () => { tabSelecting("Bold"); } }}>

…………….

                                    </RibbonItemsDirective>

                                </RibbonCollectionDirective>

                            </RibbonCollectionsDirective>

                        </RibbonGroupDirective>

                    </RibbonGroupsDirective>

                </RibbonTabDirective>

            </RibbonTabsDirective>

        </RibbonComponent>

        <div id="default-ribbonPlaceHolder">

            <div>Rich Text Editor 1</div>

            <RichTextEditorComponent id="rich_text_editor_one" toolbarSettings={toolbarSettings} focus={focus} >

                <Inject services={[HtmlEditor, Toolbar, Image, Link, QuickToolbar, Table, Video, Audio, PasteCleanup]} />

            </RichTextEditorComponent>

            ……………………….

        </div>

    </div>);

};

export default Default;

 


Video GIF:



Sample : https://stackblitz.com/edit/react-xroykq-dsgg22?file=index.js,index.css


Documentation :

https://ej2.syncfusion.com/react/documentation/rich-text-editor/exec-command


Ribbon API

https://ej2.syncfusion.com/react/documentation/api/ribbon


Rich Text Editor API

https://ej2.syncfusion.com/react/documentation/api/rich-text-editor/#focus

https://ej2.syncfusion.com/react/documentation/api/rich-text-editor/#toolbarsettings


Regards,

Vinothkumar



RS Robert Saddler September 23, 2024 09:20 PM UTC

Hi,

I'm also trying to do this using vanilla JS.  All works except the Background Colour and Font Colour toolbar items.  The chosen colour in the picker doesn't seem accessible in args? All other buttons work fine.  This is my code:

class NotesManager {

    constructor() {

        this.rteInstances = {};

        this.activeRTE = null;


        // Initialize RTEs

        this.initRTEs();


        // Initialize shared toolbar

        this.initSharedToolbar();

    }


    initRTEs() {

        const self = this;


        // List of RTE configurations

        const rteConfigs = [

            { id: 'general', placeholder: 'Enter general match notes here' },

            { id: 'home', placeholder: 'Enter Cardiff notes here' },

            { id: 'away', placeholder: 'Enter Ipswich notes here' }

        ];


        rteConfigs.forEach(config => {

            const rte = new ej.richtexteditor.RichTextEditor({

                // Initialize toolbar module but hide it

                toolbarSettings: {

                    enable: false

                },

                placeholder: config.placeholder,

                focus: function () {

                    self.activeRTE = this;

                }

            });

            rte.appendTo(`#${config.id}-notes`);

            this.rteInstances[config.id] = rte;

        });

    }


    initSharedToolbar() {

        const self = this;


        // Define the toolbar items

        const toolbarItems = [

            'Bold', 'Italic', 'Underline', '|',

            'BackgroundColor', 'FontColor', '|',

            'UpperCase', 'LowerCase', '|',

            'OrderedList', 'UnorderedList'

        ];


        // Create the shared toolbar using RichTextEditor

        this.sharedRTE = new ej.richtexteditor.RichTextEditor({

            toolbarSettings: {

                items: toolbarItems

            },

            value: '',

            toolbarClick: function (args) {

                if (self.activeRTE) {

                    const commandMap = {

                        'Bold': 'bold',

                        'Italic': 'italic',

                        'Underline': 'underline',

                        'UpperCase': 'uppercase',

                        'LowerCase': 'lowercase',

                        'OL': 'insertOrderedList',

                        'UL': 'insertUnorderedList',

                        'BackgroundColor': 'backColor',

                        'FontColor': 'fontColor'

                    };


                    const commandName = commandMap[args.item.subCommand || args.item.command];


                    if (commandName === 'fontColor' || commandName === 'backColor') {

                        // For color commands, pass the color value

                        self.activeRTE.executeCommand(commandName);

                    } else {

                        self.activeRTE.executeCommand(commandName);

                    }

                }

            },

            created: function () {

                // Hide the content area

                this.contentModule.getEditPanel().style.display = 'none';

            }

        });


        this.sharedRTE.appendTo('#shared-toolbar');

    }



RS Robert Saddler September 23, 2024 11:03 PM UTC

Throws this error when selecting, for example, the first 6 chars to colorise - looks like the color palette controls are trying to reference the sharedRTE content rather that the target RTE.  How can I reference the target RTE content instead?

ej2.min.js:1 Uncaught IndexSizeError: Failed to execute 'setEnd' on 'Range': There is no child at offset 6.

    at e.setRangePoint (ej2.min.js:1:11867982)

    at e.restore (ej2.min.js:1:11868131)

    at e.onSelectionRestore (ej2.min.js:1:12229232)

    at e.notify (ej2.min.js:1:790031)

    at t.notify (ej2.min.js:1:896908)

    at t.change (ej2.min.js:1:11891348)

    at e.notify (ej2.min.js:1:790031)

    at t.trigger (ej2.min.js:1:820077)

    at t.triggerEvent (ej2.min.js:1:1599943)

    at t.paletteClickHandler (ej2.min.js:1:1594933)



VY Vinothkumar Yuvaraj Syncfusion Team September 24, 2024 01:50 PM UTC

Hi Robert Saddler,

 

We have now migrated that sample to JavaScript, adding the font color feature in the Ribbon component and applying it to the selected text using the executeCommand method in the editor. Please refer to the following sample and video for your reference.

 

Sample : https://stackblitz.com/edit/tuzcjj-l42agl?file=index.js,index.html

 

Video GIF:

 

 

We did not encounter any of the errors you reported. Could you kindly share the entire code snippet of your sample or modify the sample we shared to replicate the issue? This will help us validate the problem further on our end.

 

Ribbon Documentation: https://ej2.syncfusion.com/javascript/documentation/ribbon/es5-getting-started  

 

API Link: https://ej2.syncfusion.com/javascript/documentation/rich-text-editor/exec-command


Regards,
Vinothkumar


Loader.
Up arrow icon