Skip to content

Commit 928e2d2

Browse files
authored
Merge pull request #247 from ckeditor/i/246
Feature: Added `disableTwoWayDataBinding` property that allows disabling the two-way data binding. It increases performance when working with large documents. Closes #246.
2 parents 8d94b65 + 38e7de6 commit 928e2d2

File tree

7 files changed

+88
-2
lines changed

7 files changed

+88
-2
lines changed

demo/src/App.vue

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<ckeditor
55
v-model="data"
66
tag-name="textarea"
7+
:disable-two-way-data-binding="isTwoWayDataBindingDisabled"
78
:editor="ClassicEditor"
89
:config="config"
910
:disabled="disabled"
@@ -18,6 +19,17 @@
1819
{{ disabled ? 'Enable' : 'Disable' }} editor
1920
</button>
2021

22+
<button @click="toggleTwoWayBinding">
23+
{{ isTwoWayDataBindingDisabled ? 'Enable' : 'Disable' }} two way binding
24+
</button>
25+
26+
<button
27+
v-if="isTwoWayDataBindingDisabled"
28+
@click="setEditorData"
29+
>
30+
Set editor data
31+
</button>
32+
2133
<h2>Live editor data</h2>
2234

2335
<textarea v-model="data" />
@@ -33,11 +45,21 @@ const data = ref( '<p>Hello world!</p>' );
3345
3446
const disabled = ref( false );
3547
48+
const isTwoWayDataBindingDisabled = ref( false );
49+
3650
const config = reactive( {
3751
toolbar: [ 'heading', '|', 'bold', 'italic' ]
3852
} );
3953
4054
// Methods
55+
function setEditorData() {
56+
data.value = window.editor.getData();
57+
}
58+
59+
function toggleTwoWayBinding() {
60+
isTwoWayDataBindingDisabled.value = !isTwoWayDataBindingDisabled.value;
61+
}
62+
4163
function toggleEditorDisabled() {
4264
disabled.value = !disabled.value;
4365
}

dist/ckeditor.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ declare const _default: import("vue").DefineComponent<{
3131
type: BooleanConstructor;
3232
default: boolean;
3333
};
34+
disableTwoWayDataBinding: {
35+
type: BooleanConstructor;
36+
default: boolean;
37+
};
3438
}, unknown, CKEditorComponentData, {}, {
3539
setUpEditorEvents(): void;
3640
}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:modelValue" | "ready" | "destroy" | "blur" | "focus" | "input")[], "update:modelValue" | "ready" | "destroy" | "blur" | "focus" | "input", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
@@ -56,6 +60,10 @@ declare const _default: import("vue").DefineComponent<{
5660
type: BooleanConstructor;
5761
default: boolean;
5862
};
63+
disableTwoWayDataBinding: {
64+
type: BooleanConstructor;
65+
default: boolean;
66+
};
5967
}>> & {
6068
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
6169
onReady?: ((...args: any[]) => any) | undefined;
@@ -68,5 +76,6 @@ declare const _default: import("vue").DefineComponent<{
6876
disabled: boolean;
6977
config: EditorConfig;
7078
tagName: string;
79+
disableTwoWayDataBinding: boolean;
7180
}>;
7281
export default _default;

dist/ckeditor.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/ckeditor.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/plugin.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ declare const _default: {
3434
type: BooleanConstructor;
3535
default: boolean;
3636
};
37+
disableTwoWayDataBinding: {
38+
type: BooleanConstructor;
39+
default: boolean;
40+
};
3741
}, unknown, import("./ckeditor").CKEditorComponentData, {}, {
3842
setUpEditorEvents(): void;
3943
}, Vue.ComponentOptionsMixin, Vue.ComponentOptionsMixin, ("update:modelValue" | "ready" | "destroy" | "blur" | "focus" | "input")[], "update:modelValue" | "ready" | "destroy" | "blur" | "focus" | "input", Vue.VNodeProps & Vue.AllowedComponentProps & Vue.ComponentCustomProps, Readonly<Vue.ExtractPropTypes<{
@@ -59,6 +63,10 @@ declare const _default: {
5963
type: BooleanConstructor;
6064
default: boolean;
6165
};
66+
disableTwoWayDataBinding: {
67+
type: BooleanConstructor;
68+
default: boolean;
69+
};
6270
}>> & {
6371
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
6472
onReady?: ((...args: any[]) => any) | undefined;
@@ -71,6 +79,7 @@ declare const _default: {
7179
disabled: boolean;
7280
config: import("@ckeditor/ckeditor5-core").EditorConfig;
7381
tagName: string;
82+
disableTwoWayDataBinding: boolean;
7483
}>;
7584
};
7685
export default _default;

src/ckeditor.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ export default defineComponent( {
4545
disabled: {
4646
type: Boolean,
4747
default: false
48+
},
49+
disableTwoWayDataBinding: {
50+
type: Boolean,
51+
default: false
4852
}
4953
},
5054

@@ -174,6 +178,10 @@ export default defineComponent( {
174178
// is set twice in a time span shorter than the debounce time.
175179
// See https://github.com/ckeditor/ckeditor5-vue/issues/149.
176180
const emitDebouncedInputEvent = debounce( evt => {
181+
if ( this.disableTwoWayDataBinding ) {
182+
return;
183+
}
184+
177185
// Cache the last editor data. This kind of data is a result of typing,
178186
// editor command execution, collaborative changes to the document, etc.
179187
// This data is compared when the component modelValue changes in a 2-way binding.

tests/ckeditor.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,44 @@ describe( 'CKEditor Component', () => {
295295
} );
296296
} );
297297

298+
describe( '#disableTwoWayDataBinding', () => {
299+
it( 'should set disableTwoWayDataBinding to false by default', async () => {
300+
const { wrapper, vm } = mountComponent();
301+
302+
await nextTick();
303+
304+
expect( vm.disableTwoWayDataBinding ).to.equal( false );
305+
306+
wrapper.unmount();
307+
} );
308+
309+
it( 'should not update #modelValue when disableTwoWayDataBinding is true', async () => {
310+
const { wrapper, vm } = mountComponent( { disableTwoWayDataBinding: true } );
311+
312+
sandbox.stub( ModelDocument.prototype, 'on' );
313+
314+
await nextTick();
315+
316+
sandbox.stub( vm.instance.data, 'get' ).returns( 'foo' );
317+
318+
const on = vm.instance.model.document.on;
319+
const evtStub = {};
320+
321+
expect( on.calledOnce ).to.be.true;
322+
expect( on.firstCall.args[ 0 ] ).to.equal( 'change:data' );
323+
324+
expect( wrapper.emitted().input ).to.be.undefined;
325+
326+
on.firstCall.args[ 1 ]( evtStub );
327+
328+
await timeout( 350 );
329+
330+
expect( wrapper.emitted().input ).to.be.undefined;
331+
332+
wrapper.unmount();
333+
} );
334+
} );
335+
298336
it( '#instance should be defined', async () => {
299337
const { wrapper, vm } = mountComponent();
300338

0 commit comments

Comments
 (0)