Create a WYSIWYG editor type field for Formly Forms using TinyMCE

Learn how to create a custom field type in angular using formly forms and TinyMCE

Requirements

Setup / Installation

  1. Add formly and TinyMCE to your project
# Formly
ng add @ngx-formly/schematics --ui-theme=bootstrap
# TinyMCE
npm install @tinymce/tinymce-angular
npm install --save tinymce # Optional
  1. Lazy loading TinyMCE dependencies
{
  "version": 1,
  "projects": {
    "app-name": {
      "architect": {
        "build": {
            "assets": [
              ...
              {
                "glob": "**/*",
                "input": "./node_modules/tinymce",
                "output": "/tinymce/"
              }
            ]
            ...
        }
      }
    }
  }
}

In the configuration above we tell angular to look inside ./node_modules/tinymce directory whenever we request assets from the path /tinymce/. This enables us to inject dependencies whenever needed rather than including them globally.

Now we can inject tinymce/tinymce.min.js in the component where we register our formly components.

import { EditorModule, TINYMCE_SCRIPT_SRC } from "@tinymce/tinymce-angular";
/* ... */
@NgModule({
  /* ... */
  imports: [
    EditorModule,

    // Formly
    ReactiveFormsModule,
    FormsModule,
    FormlyModule.forRoot({
      types: [],
    }),
  ],
  providers: [
    { provide: TINYMCE_SCRIPT_SRC, useValue: "tinymce/tinymce.min.js" },
  ],
})
export class CustomFormlyModule {}
  1. Create the formly components
import { Component, OnInit } from "@angular/core";
import { FieldType } from "@ngx-formly/material";
import { FormControl } from "@angular/forms";
import { TINYMCE_DEFAULT_CONFIG } from "../../../config";

@Component({
  selector: "formly-editor-type",
  templateUrl: "./editor-type.component.html",
})
export class EditorTypeComponent extends FieldType implements OnInit {
  readonly formControl: FormControl;

  tinyMceConfig = {
    base_url: "/tinymce",
    suffix: ".min",
    contextmenu: false,
    branding: false,
    menubar: false,
    height: 400,

    plugins: [
      "advlist autolink lists link image charmap print preview anchor",
      "searchreplace visualblocks code fullscreen",
      "insertdatetime media table paste",
    ],

    toolbar: "undo redo | formatselect | link | bold italic | bullist numlist",
  };

  ngOnInit() {
    super.ngOnInit();
  }
}
<h3>{{to.label}}</h3>
<editor
  [init]="tinyMceConfig"
  [formControl]="formControl"
  [formlyAttributes]="field"
></editor>
  1. Declare the custom component in our module
import { EditorModule, TINYMCE_SCRIPT_SRC } from '@tinymce/tinymce-angular';
import { EditorTypeComponent } from './components/editor/editor-type.component';

/* ... */
@NgModule({
  /* ... */
  imports: [
    EditorModule,

    // Formly
    ReactiveFormsModule,
    FormsModule,
    FormlyModule.forRoot({
      types: [
        {
          name: 'editor',
          component: EditorTypeComponent,
        },
      ],
    })
  ],
  providers: [
    { provide: TINYMCE_SCRIPT_SRC, useValue: 'tinymce/tinymce.min.js' }
  ],
  declarations: [EditorTypeComponent]
})
export class CustomFormlyModule {}

Usage

import { Component } from "@angular/core";
import { FormGroup } from "@angular/forms";
import { FormlyFieldConfig } from "@ngx-formly/core";

@Component({
  template: `
    <form [formGroup]="form" (ngSubmit)="onSubmit(model)">
      <formly-form
        [form]="form"
        [fields]="fields"
        [model]="model"
      ></formly-form>
      <button type="submit" class="btn btn-default">Submit</button>
    </form>
  `,
})
export class AppComponent {
  form = new FormGroup({});
  model = {};
  fields: FormlyFieldConfig[] = [
    {
      key: "content",
      type: "editor",
      templateOptions: {
        label: "Article Content",
      },
    },
  ];

  onSubmit() {
    console.log(this.model);
  }
}

You can now use a TinyMCE editor in your formly forms and store some HTML data for your needs.

More posts in JavaScript