tinymce-vue
tinymce-vue copied to clipboard
Cannot read property 'init' of null
Hi, I've imported the Editor in my app and registered it as a global component :
import Editor from '@tinymce/tinymce-vue';
Vue.component('tinymce', Editor);
Then I have :
<tinymce inline v-model="content">
Hello !
</tinymce>
But Chrome display the error below :
Editor.js?f88d:46 Uncaught TypeError: Cannot read property 'init' of null at eval (Editor.js?f88d:46) at eval (ScriptLoader.js?0fea:34) at Array.forEach (
) at HTMLScriptElement.eval (ScriptLoader.js?0fea:34)
I'm sure I missed something, but what ?
thanks !!
I can't reproduce this in my testing, can you share some more code on how you are using the component? One thing I see in your code though is that you shouldn't have any children inside of the editor component, you should add content via the v-model or initialContent.
Thanks @fyrkant. I think this is because I am loading the editor in a component that is loaded dynamically in a loop, whose syntax is :
<div v-for="(item, index) in structure" :key="index">
<component :is="item.component"></component>
</tr>
where item.component is the name of the component I want to load. The code of one of this possible dynamic component is :
<template>
<!-- section wrap START -->
<td align="center" valign="top">
<tinymce inline v-model="content"></tinymce>
</td>
<!-- section wrap END -->
</template>
<script>
import Editor from '@tinymce/tinymce-vue';
export default {
components: {
'tinymce': Editor,
},
data () {
return {
content: '<p>Hello</p>',
};
},
};
</script>
It seems the editor is not initialized correctly in this pattern of loading components dynamically. What do you think ?
Yes that is probably why it's not working, but I don't really have any idea on how to fix that I'm afraid. What do you gain from loading components in a loop like that?
Finally I found that it's because I load the component in a parent component which renders to an
TestPage.vue (component loaded by the main Vue App on route /test
):
<template>
<i-frame>
<div v-for="index in [0,1,2]" :key="index">
<component :is="type"></component>
</div>
</i-frame>
</template>
<script>
import Vue from 'vue';
import Editor from '@tinymce/tinymce-vue';
import Section from '@/components/template/Section';
Vue.component('i-frame', {
render (createElement) {
return createElement('iframe', {
on: {
load: this.renderChildren,
}
});
},
beforeUpdate () {
// freezing to prevent unnecessary reactivity of vNodes
this.previewApp.children = Object.freeze(this.$slots.default);
},
methods: {
renderChildren () {
const children = this.$slots.default;
const body = this.$el.contentDocument.body;
const el = document.createElement('div');
body.appendChild(el);
const previewApp = new Vue({
name: 'previewApp',
data: {
// freezing to prevent unnecessary reactivity of vNodes
children: Object.freeze(children),
},
render (createElement) {
return createElement('div', this.children);
},
});
previewApp.$mount(el);
this.previewApp = previewApp;
},
}
});
export default {
data () {
return {
type: 'mysection',
};
},
components: {
'mysection': Section,
}
};
</script>
Section.vue :
<template>
<div>
<tinymce v-model="content"></tinymce>
</div>
</template>
<script>
export default {
data () {
return {
content: '<p>Hello</p>',
};
},
};
</script>
I have tried to add the Editor as a component of the iframe Vue App but it does not work, by adding :
components: {
'tinymce': Editor,
},
below Vue.component('i-frame', {
but it still does not work, same error.
I don't know enough about how Vue works to be able to help you, I'm afraid. I'll set a help wanted tag on this issue and maybe someone else can help.
Thanks. I keep searching... I'll post the solution when I find one... hopefully.
I have created a codepen : https://codepen.io/ligne13/pen/PXVoKx?editors=1010 The error does not always show up in the Console (probably because of the codepen environment) but you can see that the editor is not loaded inside the iframe.
I think I've understood what the problem is now, will try to push out a fix tomorrow.
Thank you @fyrkant. In the mean time, I've asked the tiny team about this and here is what they answered :
THEM : For our Cloud platform to work the request for the editor code needs to have the Referer header included. When you create an iframe with no src attribute the browser does not appear to send a Referer header so our platform does not deliver the editor code as we cannot confirm that the domain is valid for the API key. ME: OK. So, in order to work within an iframe, should I use a self-hosted distribution ? (import via npm). THEM : That would resolve the issue you are seeing - yes. Our Cloud platform uses domains to ensure that your key is used when and where you want it to be used so any scenario where the domain cannot be determined will lead to issues with the Cloud platform.
But I'm not sure this is the real problem. Because I can see in the console that the tinymce script is loaded correctly in the window.
If you can find what is causing the issue, with the help of my codepen, that would be great !
As far as I can understand the problem is that the tinymce global is not available in the inner iframe due to how the component loads the tinymce script in the page. To fix this was more complicated then first expected so I'm sorry but I don't have the time to do it now, seeing how you are using the component is very much an edge case. I'll leave this issue open if somebody else want's to take a stab at it.