Fixed #2842 - Editor Quill: SSR error document is not defined

pull/2910/head
mertsincan 2022-08-29 11:08:07 +01:00
parent af8efc4c3a
commit 7bdbeecf69
6 changed files with 133 additions and 41 deletions

View File

@ -28,6 +28,12 @@ const EditorProps = [
type: "any",
default: "null",
description: "Inline style of the container."
},
{
name: 'modules',
type: 'object',
default: 'null',
description: 'Modules configuration, see <a href="http://quilljs.com/docs/modules/">here</a> for available options.'
}
];
@ -98,6 +104,17 @@ const EditorEvents = [
description: "Text editor instance."
}
]
},
{
name: 'load',
description: 'Callback to invoke when the quill modules are loaded.',
arguments: [
{
name: 'event.instance',
type: 'any',
description: 'Quill instance'
}
]
}
];

View File

@ -51,6 +51,13 @@ export interface EditorSelectionChangeEvent {
instance: any;
}
export interface EditorLoadEvent {
/**
* Text editor instance.
*/
instance: any;
}
export interface EditorProps {
/**
* Value of the content.
@ -72,6 +79,10 @@ export interface EditorProps {
* Inline style of the container.
*/
editorStyle?: any;
/**
* Modules configuration, see [here](https://quilljs.com/docs/modules/) for available options.
*/
modules?: any;
}
export interface EditorSlots {
@ -97,6 +108,11 @@ export declare type EditorEmits = {
* @param {EditorSelectionChangeEvent} event - Custom selection change event.
*/
'selection-change': (event: EditorSelectionChangeEvent) => void;
/**
* Callback to invoke when the quill modules are loaded.
* @param {EditorLoadEvent} event - Custom load event.
*/
'load': (event: EditorLoadEvent) => void;
}
declare class Editor extends ClassComponent<EditorProps, EditorSlots, EditorEmits> { }

View File

@ -48,17 +48,26 @@
</template>
<script>
import Quill from "quill";
import { DomHandler } from 'primevue/utils';
const QuillJS = (function () {
try {
return window.Quill;
} catch {
return null;
}
})();
export default {
name: 'Editor',
emits: ['update:modelValue', 'text-change', 'selection-change'],
emits: ['update:modelValue', 'text-change', 'selection-change', 'load'],
props: {
modelValue: String,
placeholder: String,
readonly: Boolean,
formats: Array,
editorStyle: null
editorStyle: null,
modules: null
},
quill: null,
watch: {
@ -69,59 +78,91 @@ export default {
}
},
mounted() {
this.quill = new Quill(this.$refs.editorElement, {
const configuration = {
modules: {
toolbar: this.$refs.toolbarElement
toolbar: this.$refs.toolbarElement,
...this.modules
},
readOnly: this.readonly,
theme: 'snow',
formats: this.formats,
placeholder: this.placeholder
});
};
this.renderValue(this.modelValue);
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.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.initQuill();
}
})
.then(() => {
this.handleLoad();
});
}
});
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
})
});
}
},
methods: {
renderValue(value) {
if (this.quill) {
if (value)
this.quill.pasteHTML(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 });
}
}
},
beforeUnmount() {

View File

@ -495,6 +495,10 @@ export default {
(element)[methodName].apply(element, args);
},
isExist(element) {
return element !== null && typeof element !== 'undefined' && element.nodeName && element.parentNode;
},
isClient() {
return !!(typeof window !== 'undefined' && window.document && window.document.createElement);
},

View File

@ -42,6 +42,7 @@ export declare class DomHandler {
static resolveUserAgent(): { browser: string; version: string; };
static isVisible(el: HTMLElement): boolean;
static invokeElementMethod(el: HTMLElement, methodName: string, args: any): void;
static isExist(el: HTMLElement): boolean;
static isClient(): boolean;
static getFocusableElements(el: HTMLElement, selector?: string): any[];
static getFirstFocusableElement(el: HTMLElement, selector?: string): any;

View File

@ -77,6 +77,14 @@ import Editor from 'primevue/editor';
<td>any</td>
<td>null</td>
<td>Inline style of the container.</td>
</tr>
<tr>
<td>modules</td>
<td>object</td>
<td>null</td>
<td>
Modules configuration, see <a href="http://quilljs.com/docs/modules/">here</a> for available options.
</td>
</tr>
</tbody>
</table>
@ -111,6 +119,11 @@ import Editor from 'primevue/editor';
event.textValue: Current value as text.<br/>
event.instance: Text editor instance.</td>
<td>Callback to invoke when selection of the text changes.</td>
</tr>
<tr>
<td>load</td>
<td>event.instance: Quill instance</td>
<td>Callback to invoke when the quill modules are loaded.</td>
</tr>
</tbody>
</table>
@ -253,7 +266,7 @@ export default {
'browser-source': {
tabName: 'Browser Source',
imports: `<script src="https://unpkg.com/quill/dist/quill.min.js"><\\/script>
<script src="https://unpkg.com/primevue@^3/editor/editor.min.js"><\\/script>`,
content: `<div id="app">
<h5>Default</h5>
@ -298,4 +311,4 @@ export default {
}
}
}
</script>
</script>