mat-contenteditable

Angular contenteditable directive for Angular forms and Material Design

Usage no npm install needed!

<script type="module">
  import matContenteditable from 'https://cdn.skypack.dev/mat-contenteditable';
</script>

README

Angular contenteditable directive for Angular forms and Material Design

What is this library

This is micro Angular v6+ contenteditable directive for compatibility with Angular forms. It just implements ControlValueAccessor for this purpose.

What is this fork

It implements MatFormFieldControl to support Angular Material

CSS tricks

I found some useful CSS that can be used with this lib

/* mat-editor should be applied to the container of contenteditable (<mat-form-field>)*/
.mat-editor .mat-form-field-wrapper,
.mat-editor .mat-form-field-infix {
  padding-top: 0;
  padding-bottom: 0;
}

.mat-editor .mat-form-field-flex {
  align-items: center;
}

/* https://github.com/angular/material2/issues/13322 */
.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon-button,
.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon-button {
  display: inline-block !important;
}

CKEditor5 support

There are 2 directives that can be used with CKEditor5.

matCkeditor simply implements MatFormFieldControl

<ckeditor matCkeditor [editor]="ckEditor" [(ngModel)]="content"></ckeditor>

matCkeditorBalloon should be used with @ckeditor/ckeditor5-build-balloon and has an extra input to toggle toolbar of ckeditor.

Screenshot

<mat-form-field appearance="outline" class="mat-editor">
  <ckeditor matCkeditorBalloon [toolbar]="toolbarStatus"
    [editor]="ckEditor" (ready)="editorReady($event)" [config]="editorConfig"
    [(ngModel)]="content">
  </ckeditor>
  <button matSuffix mat-icon-button type="button"
    color="{{toolbarStatus && 'primary'}}" (click)="toolbarStatus = !toolbarStatus">
    <mat-icon> tune </mat-icon>
  </button>
</mat-form-field>

To remove the border of CKEditor

.mat-editor .ck-content {
  border: none !important;
  box-shadow: none !important;
}

To adjust form-field height

<!-- make mat-form-field fill parent height -->
<div fxLayout="column">
  <mat-form-field appearance="outline" fxFlex formFieldSizer></mat-form-field>
</div>

Install

You can just copy and paste this directive or install it from npm:

npm install mat-contenteditable --save

Usage

Import and add MatContenteditableModule to your project:

import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatContenteditableModule } from 'mat-contenteditable';

// ...

@NgModule({
  // ...
  imports: [
    // Import this module to get available work angular with `contenteditable`
    MatContenteditableModule,
    // Import one or both of this modules
    FormsModule,
    ReactiveFormsModule
  ]

// ...

})

And then you can to use it in template-driven forms or reactive forms like this:

// In your component
import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';

export class MyComponent implements OnInit {
  templateDrivenForm = 'This is contenteditable text for template-driven form';
  myControl = new FormControl;

  ngOnInit() {
    this.myControl.setValue(`This is contenteditable text for reactive form`);
  }
}
<form #testForm="ngForm">
  <p
    contenteditable="true"
    name="myFormName"
    [(ngModel)]="templateDrivenForm"
    ></p>
</form>

<pre>
  {{ testForm.value | json }}
</pre>

<hr>

<p contenteditable="true" [formControl]="myControl"></p>

<pre>
  {{ myControl.value | json }}
</pre>

Options

With contenteditable directive you can pass optional @Input value for propValueAccessor:

<p
  contenteditable="true"
  propValueAccessor="textContent"
  [formControl]="myControl"
  ></p>

In ContenteditableDirective this value use like this:

this.elementRef.nativeElement[this.propValueAccessor]

By default it using innerHTML.