Angular Application

  • 6 minutes to read

This topic describes how to add the client-side RichEdit control to an Angular application.

Prerequisites

  • In the command prompt, install the Angular CLI (command line interface tool) globally:

    npm install -g @angular/cli
    

    Refer to the Angular documentation for information on the application's structure and the created file purpose.

Requirements

  • To use the RichEdit control in an Angular application, you need to have a Universal, DXperience, or ASP.NET subscription.
  • Versions of the devexpress npm packages should be identical (their major and minor versions should be the same).

Create Application with RichEdit

Create Angular Application

In the command prompt, create an Angular application and navigate to the created folder:

ng new richedit-angular-app
cd richedit-angular-app

Install RichEdit Package

The devexpress-richedit npm package references devextreme as peerDependencies. The peerDependencies packages should be installed manually. This allows developers to control a version of the peerDependencies packages and guarantees that the package is installed once.

Install a RichEdit package with required peerDependencies:

npm install devextreme devexpress-richedit --save

You can find all the libraries in the node_modules folder after the installation is completed.

Create New RichEdit Component

In the console window, use the ng generate component command to generate a new RichEdit component:

ng generate component richedit

Configure Component Class

Replace the content of the richedit.component.ts file with the code below to import the required decorators and modules, and configure the RichEdit component:

import { Component, ElementRef, OnDestroy, AfterViewInit } from '@angular/core';
import { create, createOptions, RichEdit } from 'devexpress-richedit';

@Component({
  selector: 'app-richedit',
  template: '<div></div>',
  styleUrls: ['./richedit.component.css']
})
export class RicheditComponent implements AfterViewInit, OnDestroy {
  private rich: RichEdit;

  constructor(private element: ElementRef) { }

  ngAfterViewInit(): void {
    const options = createOptions();
    // set options
    options.width = '1700px';
    options.height = '800px';
    this.rich = create(this.element.nativeElement.firstElementChild, options);
  }

  ngOnDestroy() {
    if (this.rich) {
      this.rich.dispose();
      this.rich = null;
    }
  }
}

Add Global Styles

Add the following global styles in src/styles.css file:

@import url("../node_modules/devextreme/dist/css/dx.common.css");
@import url("../node_modules/devextreme/dist/css/dx.light.css");
@import url("../node_modules/devexpress-richedit/dist/dx.richedit.css");

Register Application Component

Insert the following code at the beginning of the src/app/app.component.html file to add a component reference:

<app-richedit></app-richedit>
<!-- ... -->

Run the Application

Run the application.

ng serve --open

Localization

This section describes how to localize the ASP.NET Core RichEdit in an Angular application.

  1. Download translated resources from the DevExpress Localization Service. See the Localization Service topic to learn more.

  2. Unpack the self-extracting archive to get a folder with the localization resources.

  3. Copy the extracted resource file ~\DevExpressLocalizedResources_20.1_{lang}\json resources\dx-rich.{lang}.json to the node_modules\devexpress-richedit\localization folder.

  4. Add the following options in the compilerOptions section of the tsconfig.json file:

    {
      ...
      "compilerOptions": {
        ...
        "resolveJsonModule": true,
        "allowSyntheticDefaultImports": true,
      }
    }
    
  5. Add the following code in the src/app/app.component.ts file. Note that the code sample below imports the French localization.

    import { loadMessages, locale } from 'devextreme/localization';
    import RELocalization from 'devexpress-richedit/localization/dx-rich.fr.json';
    ...
    // load localized messages and specify the locale identifier in the constructor of the AppComponent class
    export class AppComponent {
        constructor() {
            loadMessages({ fr: RELocalization });
            locale("fr");
        }
        ...
    }
    

Examples

How to Set RichEdit Options

The code sample below demonstrates how you can set RichEdit options.

// the createOptions() method creates an object that contains RichEdit options initialized with default values
const options = createOptions();

options.bookmarks.visibility = true;
options.bookmarks.color = '#ff0000';

options.confirmOnLosingChanges.enabled = true;
options.confirmOnLosingChanges.message = 'Are you sure you want to perform the action? All unsaved document data will be lost.';

options.fields.updateFieldsBeforePrint = true;
options.fields.updateFieldsOnPaste = true;

options.mailMerge.activeRecord = 2;
options.mailMerge.viewMergedData = true;
options.mailMerge.dataSource = [
    { Name: 'Indy', age: 32 },
    { Name: 'Andy', age: 28 },
];

// events
options.events.activeSubDocumentChanged = () => { };
options.events.autoCorrect = () => { };
options.events.calculateDocumentVariable = () => { };
options.events.characterPropertiesChanged = () => { };
options.events.contentInserted = () => { };
options.events.contentRemoved = () => { };
options.events.documentChanged = () => { };
options.events.documentFormatted = () => { };
options.events.documentLoaded = () => { };
options.events.gotFocus = () => { };
options.events.hyperlinkClick = () => { };
options.events.keyDown = () => { };
options.events.keyUp = () => { };
options.events.paragraphPropertiesChanged = () => { };
options.events.lostFocus = () => { };
options.events.pointerDown = () => { };
options.events.pointerUp = () => { };
options.events.saving = () => { };
options.events.saved = () => { };
options.events.selectionChanged = () => { };    
options.events.customCommandExecuted = (s, e) => {
    switch (e.commandName) {
    case 'insertEmailSignature':
        s.document.insertParagraph(s.document.length);
        s.document.insertText(s.document.length, '_________');
        s.document.insertParagraph(s.document.length);
        s.document.insertText(s.document.length, 'Best regards,');
        s.document.insertParagraph(s.document.length);
        s.document.insertText(s.document.length, 'John Smith');
        s.document.insertParagraph(s.document.length);
        s.document.insertText(s.document.length, 'john@example.com');
        s.document.insertParagraph(s.document.length);
        s.document.insertText(s.document.length, '+1 (818) 844-0000');
        break;
    }
};

options.unit = RichEditUnit.Inch;

options.view.viewType = ViewType.PrintLayout;
options.view.simpleViewSettings.paddings = {
  left: 15,
  top: 15,
  right: 15,
  bottom: 15,
};

options.autoCorrect = {
    correctTwoInitialCapitals: true,
    detectUrls: true,
    enableAutomaticNumbering: true,
    replaceTextAsYouType: true,
    caseSensitiveReplacement: false,
    replaceInfoCollection: [
        { replace: "wnwd", with: "well-nourished, well-developed" },
        { replace: "(c)", with: "©" }
    ],
};
// capitalize the first letter at the beginning of a new sentence/line
options.events.autoCorrect = function (s, e) {
    if (e.text.length == 1 && /\w/.test(e.text)) {
        var prevText = s.document.getText(new Interval(e.interval.start - 2, 2));
        if (prevText.length == 0 || /^(\. |\? |\! )$/.test(prevText) || prevText.charCodeAt(1) == 13) {
            var newText = e.text.toUpperCase();
            if (newText != e.text) {
                s.beginUpdate();
                s.history.beginTransaction();
                s.document.deleteText(e.interval);
                s.document.insertText(e.interval.start, newText);
                s.history.endTransaction();
                s.endUpdate();
                e.handled = true;
            }
        }
    }
};  

options.exportUrl = 'https://siteurl.com/api/';

options.readOnly = false;
options.width = '800px';
options.height = '1200px';

How to Customize the Ribbon

The code sample below demonstrates how to modify the built-in ribbon.

ribbonCustomization(options: Options) {
    // remove items
    const fileTab = options.ribbon.getTab(RibbonTabType.File);
    fileTab.removeItem(FileTabItemId.OpenDocument);

    const homeTab = options.ribbon.getTab(RibbonTabType.Home);
    homeTab.removeItem(HomeTabItemId.Copy);
    homeTab.removeItem(HomeTabItemId.Cut);
    homeTab.removeItem(HomeTabItemId.Paste);

    homeTab.removeItem(HomeTabItemId.DecreaseFontSize);
    homeTab.removeItem(HomeTabItemId.IncreaseFontSize);

    homeTab.removeItem(HomeTabItemId.ChangeStyle);

    // remove element from drop down list
    // fileTab.removeItem(FileTabItemId.DownloadRtf);
    // fileTab.removeItem(FileTabItemId.DownloadTxt);

    // allow only download as docx. Create out item from default items
    const downloadDocxItem = fileTab.getItem(FileTabItemId.DownloadDocx) as RibbonSubMenuItem;
    const downloadItem = fileTab.getItem(FileTabItemId.Download) as RibbonMenuItem;
    fileTab.removeItem(FileTabItemId.Download);
    // icons: https://js.devexpress.com/Documentation/Guide/Themes_and_Styles/Icons/
    fileTab.insertItem(new RibbonButtonItem(downloadDocxItem.id, downloadItem.text, {icon: downloadItem.icon, showText: true}), 2);

    // move items to new tab
    const findElem: RibbonItem = homeTab.getItem(HomeTabItemId.Find);
    const replaceElem: RibbonItem = homeTab.getItem(HomeTabItemId.Replace);
    homeTab.removeItem(findElem);
    homeTab.removeItem(replaceElem);

    // remove tab
    options.ribbon.removeTab(RibbonTabType.References);

    // insert tab
    const findTabId = 'FindTabId';
    const newFindTab = options.ribbon.insertTab(new RibbonTab('Find', findTabId, [findElem, replaceElem]), 2);

    // add custom item
    const findInGoogleId = 'FindInGoogleId';
    newFindTab.insertItem(new RibbonButtonItem(findInGoogleId, 'Find in Google', { beginGroup: true }));
    options.events.customCommandExecuted = (s, e) => {
      if (e.commandName === findInGoogleId) {
        const selectedInterval = s.selection.intervals[0];
        if (selectedInterval.length > 0) {
          const selectedText = s.selection.activeSubDocument.getText(selectedInterval);
          window.open(`https://www.google.com/search?q=${selectedText}`, '_blank');
        }
      }
    };
}