Build a rich text editor in Angular with ngx-quill
Tags: angular, typescript, css, jiraclone
Published: 2020-11-04 11:51:29


If you notice, the current [jira.trungk18.com][jira] is using a rich text HTML editor. This tutorial will help you to create one using `ngx-quill`.

That's how a rich text editor looks.

![Angular Jira Clone Part 07 - Build a rich text editor](https://dev-to-uploads.s3.amazonaws.com/i/ih9rkjbdt2461xryuqt8.gif)

See [all tutorials for Jira clone](https://trungk18.com/tags/jira-clone/)

## Source code and demo

{% stackblitz angular-markdown-editor-jira view=preview %}

## Rich Editor Module

Like a markdown text editor, I will reuse a rich text editor in many places on a web application. So that I will create a brand new module, `RichTextEditorModule`, for that purpose. At the moment, it will have only one component, `RichTextEditorComponent`.

![Angular Jira Clone Part 07 - Build a rich text editor](https://dev-to-uploads.s3.amazonaws.com/i/nc23ksicqfj2wwj16xvs.png)
 
There is not much code inside its module and component.

rich-text-editor.component.ts

```ts
@Component({
  selector: 'rich-text-editor',
  templateUrl: './rich-text-editor.component.html',
  styleUrls: ['./rich-text-editor.component.css'],
})
export class RichTextEditorComponent implements OnInit {
  constructor() {}
  ngOnInit() {}
}
```

rich-text-editor.module.ts

```ts
@NgModule({
  imports: [CommonModule],
  exports: [RichTextEditorComponent],
  declarations: [RichTextEditorComponent],
})
export class MarkdownEditorModule {}
```

No worry, we will add more code to the component. 😆

## ngx-quill

To build a rich text editor from scratch could take me the same time to make the whole Jira clone application. That's why I am utilizing [ngx-quill][ngx-quill].

ngx-quill is an angular module for the [Quill Rich Text Editor][quill] containing all components you need.

### Installation

```bash
npm install ngx-quill
```

For projects using Angular < v5.0.0, please run.

```bash
npm install ngx-quill@1.6.0
```

### Basic Usage

#### 1. Import `QuillModule` into your `AppModule`

```ts
@NgModule({
  imports: [
    ...,

    QuillModule.forRoot()
  ],
  ...
})
class AppModule { ... }
```

#### 2. Import `QuillModule` into `RichTextEditorModule`

```ts
import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
import { RichTextEditorComponent } from './rich-text-editor.component'
import { QuillModule } from 'ngx-quill'

@NgModule({
  imports: [CommonModule, QuillModule],
  declarations: [RichTextEditorComponent],
  exports: [RichTextEditorComponent],
})
export class RichTextEditorModule {}
```

#### 3. Import quill themes CSS into `styles.scss`

```css
@import '~quill/dist/quill.core.css';
@import '~quill/dist/quill.snow.css';
```

### Build our customize rich text editor component

I can now use <quill-editor></quill-editor> in the `RichTextEditorComponent`. I will go ahead and place that HTML in my component template. I set a class name `content-editor` so that I can style it later.

```html
<quill-editor class="content-editor" [placeholder]="''"> </quill-editor>
```

See the result. Because quill is a compelling library, the rendered component has a textbox and most of the default toolbar button available for us.

![Angular Jira Clone Part 07 - Build a rich text editor](https://dev-to-uploads.s3.amazonaws.com/i/tw7lvsixtec75q6z3q6n.gif)
 
My job now is pretty simple to customize the component with only the button that I need and some CSS styling.

### Toolbar configuration

Below is the current configuration that I use for one toolbar row with some basic commands.

```ts
export const QuillConfiguration = {
  toolbar: [
    ['bold', 'italic', 'underline', 'strike'],
    ['blockquote', 'code-block'],
    [{ list: 'ordered' }, { list: 'bullet' }],
    [{ header: [1, 2, 3, 4, 5, 6, false] }],
    [{ color: [] }, { background: [] }],
    ['link'],
    ['clean'],
  ],
}
```

And then I passed it down to `modules` input of the `quill-editor`

```html
<quill-editor
  class="content-editor"
  [placeholder]="''"
  [modules]="quillConfiguration"
>
</quill-editor>
```

That's the result with lesser command.

![Angular Jira Clone Part 07 - Build a rich text editor](https://dev-to-uploads.s3.amazonaws.com/i/emwlkcx4gbvmvpijpbwh.gif)
 
Noted that by default, `ngx-quill` will render a short textarea, and it will automatically expand to fill the height as you type. You might want to set a default `min-height`. I did set default `120px`.

```html
<quill-editor
  class="content-editor"
  [placeholder]="''"
  [modules]="quillConfiguration"
  [styles]="{'min-height': '120px'}"
>
</quill-editor>
```

I guess it looks right now. The leftover part is to connect it with a form :)

![Angular Jira Clone Part 07 - Build a rich text editor](https://dev-to-uploads.s3.amazonaws.com/i/w79ilnos2x3sa6kk0lyd.gif)
 
### Connect RichTextEditorComponent to a form

ngx-quill provided support for both `ReactiveForms` and `TemplateForm`. I shifted only to use ReactiveForms. That's why I will follow a similar approach as the Markdown component to take a `FormControl` as an `Input`.

```ts
export class RichTextEditorComponent implements OnInit {
  quillConfiguration = QuillConfiguration
  @Input() control: FormControl

  ngOnInit() {
    this.control = this.control ?? new FormControl()
  }
}
```

```html
<quill-editor
  [formControl]="control"
  [placeholder]="''"
  [modules]="quillConfiguration"
  [styles]="{'min-height': '120px'}"
  class="content-editor"
>
</quill-editor>
```

See the result when I pair it inside a form. Work perfectly.

![Angular Jira Clone Part 07 - Build a rich text editor](https://dev-to-uploads.s3.amazonaws.com/i/5x4fz20as6wuik45xp1k.gif)
 
### Homework

There is some small improvement that I leave it to you.

- Set a border when focusing into the rich text editor
- Implement [ControlValueAccessor][controlvalueaccessor] for the `RichTextEditorComponent` so that you can use both `[ngModel]` and `formControl` in a form :)

That's all for a rich text editor with Angular. Any questions, you can leave it in the comment box below or reach me on Twitter. Thanks for stopping by!

[jira]: https://jira.trungk18.com/
[icon]: https://icons.getbootstrap.com/
[editable-textbox]: https://trungk18.com/experience/angular-jira-clone-tutorial-04-editable-textbox/
[ngx-quill]: https://github.com/KillerCodeMonkey/ngx-quill
[quill]: https://quilljs.com/
[controlvalueaccessor]: https://angular.io/api/forms/ControlValueAccessor
[text-editor]: https://github.com/trungk18/jira-clone-angular/blob/feature/gql/apps/jira-clone/src/app/shared/text-editor/text-editor.component.html