Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Value is set but ckeditor area empty #50

Closed
reyhankaplan opened this issue Aug 21, 2020 · 8 comments
Closed

Value is set but ckeditor area empty #50

reyhankaplan opened this issue Aug 21, 2020 · 8 comments
Labels
resolution:cantreproduce A report that is not reproducible.

Comments

@reyhankaplan
Copy link

ckeditor4-vue version: 1.0.1

Usually the value is showed correctly but sometimes ckeditor has the value but doesn't show it.

Screenshot 2020-08-21 at 10 39 22
Screenshot 2020-08-21 at 10 51 55

This is the code in TextEditor component. I couldn't find the reason why it sometimes looks empty, and there is nothing in console. Have an idea why is this happening?

<template>
  <ckeditor
    :value="value"
    @input="(v) => $emit('input', v)"
    :config="editorConfig"
  ></ckeditor>
</template>

<script>
export default {
  props: {
    value: {
      type: String,
      default: ''
    },
    editorConfig: {
      type: Object,
      default: () => ({})
    }
  }
}
</script>
@ivanchenkoandriy
Copy link

ivanchenkoandriy commented Aug 25, 2020

зображення
зображення
зображення

@jacekbogdanski jacekbogdanski self-assigned this Aug 26, 2020
@jacekbogdanski
Copy link
Member

jacekbogdanski commented Aug 26, 2020

@ryhnnl could you provide full, minimal code required to reproduce the issue? It would be great if you could use an online editor for that, e.g.

Could you also tell me when the issue is happening? Does it happen during user iteration or on the initial editor load?

@ivanchenkoandriy could you tell how this warning is related to this issue?

@reyhankaplan
Copy link
Author

Hi @jacekbogdanski

I created a sandbox but I couldn't reproduce the issue on the sandbox, it happens rarely on our project, we have a list of blog posts, when user clicks one of them it opens the page with editor, the content in editor loaded with an http request, and user can edit and save.

Also it doesn't happen on user iteration, it happens while switching between pages.

@jmalatia
Copy link

We are experiencing a similar issue.

@ryhnnl is your <router-view> wrapped in a <keep-alive>?

Our usage with vue-router, transition, keep-alive:

<transition>
    <keep-alive>
        <router-view/>
    </keep-alive>
</transition>

Our page with ckEditor is /post/123, if we go to /post/123, then use a link to go to /aboutus and then use a link to go back to /post/123 all other form fields on our page are populated, ckEditor menus, etc. are displaying, but ckEditor html is blank/empty.

Is there a way to re-fire/refresh ckEditor?

image

@jacekbogdanski
Copy link
Member

keep-alive is not really supported by now, because it's only using lifecycle hooks during initial component creation. After that, the component is kept in memory. We could probably support it using activated and deactivated hooks instead, but for now, it's recommended to use "normal" component lifecycle, so it's recreated on every route change.

@ryhnnl could you confirm that you are using keep-alive? I didn't notice it in your code demo, but also I couldn't reproduce the issue using it.

@reyhankaplan
Copy link
Author

@jacekbogdanski @jmalatia no we are not using keep-alive in our project.

@jacekbogdanski sorry, as I told before, I tried to reproduce it, but the issue doesn't happen all the time in our project, so I don't exactly know how is that happening. My code demo only shows how we are using it in the project.

@jmalatia
Copy link

jmalatia commented Sep 11, 2020

We seem to have resolved making ckEditor compatible with keep-alive by bringing in a local copy of ckeditor4-vue and making the following changes to ckeditor.js:

  • Moved all code in mounted() to its own method which we named $_setupEditor().
  • Added a deactivated hook to destroy the editor instance and an activated hook to reinitialize the editor instance.

Not sure if it's correct, but it seems to be working as one would expect from our initial quick testing.

Our full, modified ckeditor.js

import { getEditorNamespace } from './utils/geteditornamespace.js';

export default {
    name: "ckeditor",

    render(createElement) {
        return createElement("div", {}, [createElement(this.tagName)]);
    },

    props: {
        value: {
            type: String,
            default: ""
        },
        type: {
            type: String,
            default: "classic",
            validator: type => ["classic", "inline"].includes(type)
        },
        editorUrl: {
            type: String,
            default: "https://cdn.ckeditor.com/4.15.0/standard-all/ckeditor.js"
        },
        config: {
            type: Object,
            default: () => {}
        },
        tagName: {
            type: String,
            default: "textarea"
        },
        readOnly: {
            type: Boolean,
            default: null // Use null as the default value, so `config.readOnly` can take precedence.
        }
    },

    mounted() {
        this.$_isEditorMounting = true;
        this.$_setupEditor().then(e => {
            this.$_isEditorMounting = false;
        });
    },

    beforeDestroy() {
        if (this.instance) {
            this.instance.destroy();
        }

        this.$_destroyed = true;
    },

    deactivated() {
        if (this.instance) {
            this.instance.destroy();
        }
    },

    activated() {
        if (!this.$_isEditorMounting) {
            this.$_setupEditor();
        }
    },

    watch: {
        value(val) {
            if (this.instance && this.instance.getData() !== val) {
                this.instance.setData(val);
            }
        },

        readOnly(val) {
            if (this.instance) {
                this.instance.setReadOnly(val);
            }
        }
    },

    methods: {
        $_setupEditor() {
            return getEditorNamespace(this.editorUrl).then(() => {
                if (this.$_destroyed) {
                    return;
                }

                const config = this.config || {};

                if (this.readOnly !== null) {
                    config.readOnly = this.readOnly;
                }

                const method = this.type === "inline" ? "inline" : "replace";
                const element = this.$el.firstElementChild;
                const editor = (this.instance = CKEDITOR[method](element, config));

                editor.on("instanceReady", () => {
                    const data = this.value;

                    editor.fire("lockSnapshot");

                    editor.setData(data, {
                        callback: () => {
                            this.$_setUpEditorEvents();

                            const newData = editor.getData();

                            // Locking the snapshot prevents the 'change' event.
                            // Trigger it manually to update the bound data.
                            if (data !== newData) {
                                this.$once("input", () => {
                                    this.$emit("ready", editor);
                                });

                                this.$emit("input", newData);
                            } else {
                                this.$emit("ready", editor);
                            }

                            editor.fire("unlockSnapshot");
                        }
                    });
                });
            });
        },

        $_setUpEditorEvents() {
            const editor = this.instance;

            editor.on("change", evt => {
                const data = editor.getData();

                // Editor#change event might be fired without an actual data change.
                if (this.value !== data) {
                    // The compatibility with the v-model and general Vue.js concept of input–like components.
                    this.$emit("input", data, evt, editor);
                }
            });

            editor.on("focus", evt => {
                this.$emit("focus", evt, editor);
            });

            editor.on("blur", evt => {
                this.$emit("blur", evt, editor);
            });
        }
    }
};

@jacekbogdanski
Copy link
Member

@jmalatia thanks for the code, I've extracted separate feature for that #62

@ryhnnl I'm still not able to reproduce the issue. We would need to have some real, reproducible case scenario to find out what's going on. I suppose that the issue could be connected with #52 due to the throttling of the undo plugin, but it's just a guess.

I have to close the issue for now since it's not reproducible, but if you will be able to provide some demo or code sample with the issue, we would be happy to take a look and reopen the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
resolution:cantreproduce A report that is not reproducible.
Projects
None yet
Development

No branches or pull requests

4 participants