Welcome folks today in this blog post we will be embeding WYSIWYG
advanced editor in angular app using the ngx-quill
library to build email invoice template with live preview in typescript. All the full source code of the application is shown below.
Get Started
In order to get started you need to initialize a new angular project using the below command as shown below
ng new sampleapp
cd sampleapp
Now we need to install the dependency inside the angular project as shown below
npm i ngx-quill
Now we need to include the ngx-quill
module inside the app.module.ts file as shown below
app.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 |
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { QuillModule } from 'ngx-quill' import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule, FormsModule, QuillModule.forRoot() ], declarations: [ AppComponent ], bootstrap: [ AppComponent ] }) export class AppModule { } |
As you can see we are importing the QuillModule
from ngx-quill and including it inside the imports array. As you can see we are also importing the built in FormsModule from angular/forms and adding it inside the imports array.
And now we need to edit the app.component.html
file and write the basic html required for this email editor.
app.component.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<br/> Subject: <input type="text" [(ngModel)]="subject"/> <br/> <br/> <quill-editor [(ngModel)]="htmlText" placeholder="Enter Text" [modules]="quillConfig" (onSelectionChanged)="onSelectionChanged($event)" (onContentChanged)="onContentChanged($event)"></quill-editor> <!-- <div> <pre>{{htmlText}}</pre> </div> --> <h2>Preview email will show the following</h2> Subject: {{subject}} <br/> <br/> Body: <div [innerHTML]="htmlText"> </div> |
As you can see we are adding the quill-editor
directive inside the html file and we are providing some options to it which is the actual ngModel which will store the actual text which will be written inside the editor. And then we are attaching the configuration options of the quill-editor
. And then we are attaching the different events of the editor which is onSelectionChanged
and onContextChanged
and for this events we are defining the functions. So now we need to define these functions inside the app.component.ts
file as shown below
And then we have the special preview section where we will seeing the actual email which is constructed using the editor. We will rendering here the subject of the email and also the inner content of the email.
As you can see this will be the output if you open the angular app inside the browser. Now we just need to write the typescript code inside the app.component.ts
file and just start this application
app.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
import { Component } from '@angular/core'; import 'quill-mention'; import 'quill-emoji'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: [ './app.component.css' ] }) export class AppComponent { htmlText ="<p>Testing</p>" hasFocus = false; subject: string; atValues = [ { id: 1, value: 'Fredrik Sundqvist', link: 'https://google.com' }, { id: 2, value: 'Patrik Sjölin' } ]; hashValues = [ { id: 3, value: 'Fredrik Sundqvist 2' }, { id: 4, value: 'Patrik Sjölin 2' } ] quillConfig={ //toolbar: '.toolbar', toolbar: { container: [ ['bold', 'italic', 'underline', 'strike'], // toggled buttons ['code-block'], [{ 'header': 1 }, { 'header': 2 }], // custom button values [{ 'list': 'ordered'}, { 'list': 'bullet' }], //[{ 'script': 'sub'}, { 'script': 'super' }], // superscript/subscript //[{ 'indent': '-1'}, { 'indent': '+1' }], // outdent/indent //[{ 'direction': 'rtl' }], // text direction //[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown //[{ 'header': [1, 2, 3, 4, 5, 6, false] }], //[{ 'font': [] }], //[{ 'align': [] }], ['clean'], // remove formatting button ['link'], //['link', 'image', 'video'] ], }, mention: { allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/, mentionDenotationChars: ["@", "#"], source: (searchTerm, renderList, mentionChar) => { let values; if (mentionChar === "@") { values = this.atValues; } else { values = this.hashValues; } if (searchTerm.length === 0) { renderList(values, searchTerm); } else { const matches = []; for (var i = 0; i < values.length; i++) if (~values[i].value.toLowerCase().indexOf(searchTerm.toLowerCase())) matches.push(values[i]); renderList(matches, searchTerm); } }, }, "emoji-toolbar": true, "emoji-textarea": false, "emoji-shortname": true, keyboard: { bindings: { // shiftEnter: { // key: 13, // shiftKey: true, // handler: (range, context) => { // // Handle shift+enter // console.log("shift+enter") // } // }, enter:{ key:13, handler: (range, context)=>{ console.log("enter"); return true; } } } } } constructor( ){ } test=(event)=>{ console.log(event.keyCode); } onSelectionChanged = (event) =>{ if(event.oldRange == null){ this.onFocus(); } if(event.range == null){ this.onBlur(); } } onContentChanged = (event) =>{ //console.log(event.html); } onFocus = () =>{ console.log("On Focus"); } onBlur = () =>{ console.log("Blurred"); } } |
As you can see we are defining the initial data and also the functions for various events inside the editor. And also we are attaching all the widgets to this editor which will include the ability to bold the text,underline the text and also add image and videos in editor. And also add the hyperlinks as well. All sort of widgets will be available to the user to construct the email template.