<template> <div :class="cx('root')" v-bind="ptm('root')" data-pc-name="editor"> <div ref="toolbarElement" :class="cx('toolbar')" v-bind="ptm('toolbar')"> <slot name="toolbar"> <span class="ql-formats" v-bind="ptm('formats')"> <select class="ql-header" defaultValue="0" v-bind="ptm('header')"> <option value="1" v-bind="ptm('option')">Heading</option> <option value="2" v-bind="ptm('option')">Subheading</option> <option value="0" v-bind="ptm('option')">Normal</option> </select> <select class="ql-font" v-bind="ptm('font')"> <option v-bind="ptm('option')"></option> <option value="serif" v-bind="ptm('option')"></option> <option value="monospace" v-bind="ptm('option')"></option> </select> </span> <span class="ql-formats" v-bind="ptm('formats')"> <button class="ql-bold" type="button" v-bind="ptm('bold')"></button> <button class="ql-italic" type="button" v-bind="ptm('italic')"></button> <button class="ql-underline" type="button" v-bind="ptm('underline')"></button> </span> <span :key="reRenderColorKey" class="ql-formats" v-bind="ptm('formats')"> <select class="ql-color" v-bind="ptm('color')"></select> <select class="ql-background" v-bind="ptm('background')"></select> </span> <span class="ql-formats" v-bind="ptm('formats')"> <button class="ql-list" value="ordered" type="button" v-bind="ptm('list')"></button> <button class="ql-list" value="bullet" type="button" v-bind="ptm('list')"></button> <select class="ql-align" v-bind="ptm('select')"> <option defaultValue v-bind="ptm('option')"></option> <option value="center" v-bind="ptm('option')"></option> <option value="right" v-bind="ptm('option')"></option> <option value="justify" v-bind="ptm('option')"></option> </select> </span> <span class="ql-formats" v-bind="ptm('formats')"> <button class="ql-link" type="button" v-bind="ptm('link')"></button> <button class="ql-image" type="button" v-bind="ptm('image')"></button> <button class="ql-code-block" type="button" v-bind="ptm('codeBlock')"></button> </span> <span class="ql-formats" v-bind="ptm('formats')"> <button class="ql-clean" type="button" v-bind="ptm('clean')"></button> </span> </slot> </div> <div ref="editorElement" :class="cx('content')" :style="editorStyle" v-bind="ptm('content')"></div> </div> </template> <script> import { DomHandler } from 'primevue/utils'; import BaseEditor from './BaseEditor.vue'; const QuillJS = (function () { try { return window.Quill; } catch { return null; } })(); export default { name: 'Editor', extends: BaseEditor, emits: ['update:modelValue', 'text-change', 'selection-change', 'load'], data() { return { reRenderColorKey: 0 }; }, quill: null, watch: { modelValue(newValue, oldValue) { if (newValue !== oldValue && this.quill && !this.quill.hasFocus()) { this.reRenderColorKey++; this.renderValue(newValue); } } }, mounted() { const configuration = { modules: { toolbar: this.$refs.toolbarElement, ...this.modules }, readOnly: this.readonly, theme: 'snow', formats: this.formats, placeholder: this.placeholder }; if (QuillJS) { // Loaded by script only this.quill = new QuillJS(this.$refs.editorElement, configuration); this.initQuill(); this.handleLoad(); } else { import('quill') .then((module) => { if (module && DomHandler.isExist(this.$refs.editorElement)) { if (module.default) { // webpack this.quill = new module.default(this.$refs.editorElement, configuration); } else { // parceljs this.quill = new module(this.$refs.editorElement, configuration); } this.initQuill(); } }) .then(() => { this.handleLoad(); }); } }, beforeUnmount() { this.quill = null; }, methods: { renderValue(value) { if (this.quill) { if (value) this.quill.setContents(this.quill.clipboard.convert(value)); else this.quill.setText(''); } }, initQuill() { this.renderValue(this.modelValue); this.quill.on('text-change', (delta, oldContents, source) => { if (source === 'user') { let html = this.$refs.editorElement.children[0].innerHTML; let text = this.quill.getText().trim(); if (html === '<p><br></p>') { html = ''; } this.$emit('update:modelValue', html); this.$emit('text-change', { htmlValue: html, textValue: text, delta: delta, source: source, instance: this.quill }); } }); this.quill.on('selection-change', (range, oldRange, source) => { let html = this.$refs.editorElement.children[0].innerHTML; let text = this.quill.getText().trim(); this.$emit('selection-change', { htmlValue: html, textValue: text, range: range, oldRange: oldRange, source: source, instance: this.quill }); }); }, handleLoad() { if (this.quill && this.quill.getModule('toolbar')) { this.$emit('load', { instance: this.quill }); } } } }; </script>