ckeditor / ckeditor5-vue

Official CKEditor 5 Vue.js component.
https://ckeditor.com/ckeditor-5
Other
361 stars 77 forks source link

Component is missing template or render function. #204

Closed kicker10BOG closed 2 years ago

kicker10BOG commented 2 years ago

I'm trying to use CKEditor 5 with Vue and Laravel, but I'm getting this error in the console when I try to load the page.

Vue warn]: Component is missing template or render function. 
  at <CKEditor editor=fn<ClassicEditor> modelValue="" onUpdate:modelValue=fn  ... > 
  at <BasicEditor fieldName="body" > 

Here's my BasicEditor Vue component"

<template>
  <div>
    <CKEditor :editor="editor" v-model="editorData" :config="editorConfig"></CKEditor>
    <textarea
      class="w-full hidden"
      :id="fieldName"
      :name="fieldName"
      rows="5"
      cols="20"
      required
    >
            {{ editorData }}
        </textarea
    >
  </div>
</template>

<script>
import CKEditor from "@ckeditor/ckeditor5-vue";
// ⚠️ NOTE: We don't use @ckeditor/ckeditor5-build-classic any more!
// Since we're building CKEditor from source, we use the source version of ClassicEditor.
import ClassicEditor from "@ckeditor/ckeditor5-editor-classic/src/classiceditor";

import EssentialsPlugin from "@ckeditor/ckeditor5-essentials/src/essentials";
import BoldPlugin from "@ckeditor/ckeditor5-basic-styles/src/bold";
import ItalicPlugin from "@ckeditor/ckeditor5-basic-styles/src/italic";
import LinkPlugin from "@ckeditor/ckeditor5-link/src/link";
import ParagraphPlugin from "@ckeditor/ckeditor5-paragraph/src/paragraph";

export default {
  name: "basic-editor",
  components: {
    // ckeditor: CKEditor.component
    CKEditor
  },
  props: {
    initial: {
      type: String,
      default: "",
    },
    fieldName: {
      type: String,
      default: "body",
    },
  },
  data() {
    return {
      editor: ClassicEditor,
      editorData: this.initial,
      editorConfig: {
        plugins: [
          EssentialsPlugin,
          BoldPlugin,
          ItalicPlugin,
          LinkPlugin,
          ParagraphPlugin,
        ],

        toolbar: {
          items: ["bold", "italic", "link", "undo", "redo"],
        },
      },
    };
  },
};
</script>

package.json (planning to have a basic editor and more advanced editor):

{
    "private": true,
    "scripts": {
        "dev": "npm run development",
        "development": "mix",
        "watch": "mix watch",
        "watch-poll": "mix watch -- --watch-options-poll=1000",
        "hot": "mix watch --hot",
        "prod": "npm run production",
        "production": "mix --production"
    },
    "devDependencies": {
        "@ckeditor/ckeditor5-vue": "^2.0.1",
        "@popperjs/core": "^2.10.2",
        "@tailwindcss/forms": "^0.4.0",
        "alpinejs": "^3.4.2",
        "autoprefixer": "^10.1.0",
        "axios": "^0.21",
        "babel-runtime": "^6.26.0",
        "bootstrap": "^5.1.3",
        "laravel-mix": "^6.0.41",
        "lodash": "^4.17.19",
        "postcss": "^8.2.1",
        "postcss-import": "^14.0.1",
        "resolve-url-loader": "^3.1.2",
        "sass-loader": "^11.0.1",
        "tailwindcss": "^3.0.20",
        "vue": "^3.2.30",
        "vue-loader": "^17.0.0",
        "vue-template-compiler": "^2.6.12",
        "@ckeditor/ckeditor5-alignment": "^32.0.0",
        "@ckeditor/ckeditor5-autoformat": "^32.0.0",
        "@ckeditor/ckeditor5-basic-styles": "^32.0.0",
        "@ckeditor/ckeditor5-block-quote": "^32.0.0",
        "@ckeditor/ckeditor5-code-block": "^32.0.0",
        "@ckeditor/ckeditor5-dev-utils": "^25.4.5",
        "@ckeditor/ckeditor5-dev-webpack-plugin": "^25.4.5",
        "@ckeditor/ckeditor5-editor-classic": "^32.0.0",
        "@ckeditor/ckeditor5-essentials": "^32.0.0",
        "@ckeditor/ckeditor5-font": "^32.0.0",
        "@ckeditor/ckeditor5-heading": "^32.0.0",
        "@ckeditor/ckeditor5-highlight": "^32.0.0",
        "@ckeditor/ckeditor5-horizontal-line": "^32.0.0",
        "@ckeditor/ckeditor5-html-support": "^32.0.0",
        "@ckeditor/ckeditor5-image": "^32.0.0",
        "@ckeditor/ckeditor5-indent": "^32.0.0",
        "@ckeditor/ckeditor5-link": "^32.0.0",
        "@ckeditor/ckeditor5-list": "^32.0.0",
        "@ckeditor/ckeditor5-media-embed": "^32.0.0",
        "@ckeditor/ckeditor5-paragraph": "^32.0.0",
        "@ckeditor/ckeditor5-paste-from-office": "^32.0.0",
        "@ckeditor/ckeditor5-remove-format": "^32.0.0",
        "@ckeditor/ckeditor5-source-editing": "^32.0.0",
        "@ckeditor/ckeditor5-table": "^32.0.0",
        "@ckeditor/ckeditor5-theme-lark": "^32.0.0",
        "@ckeditor/ckeditor5-typing": "^32.0.0",
        "@ckeditor/ckeditor5-upload": "^32.0.0",
        "@ckeditor/ckeditor5-word-count": "^32.0.0",
        "postcss-loader": "^4.3.0",
        "raw-loader": "^4.0.2"
    },
    "dependencies": {
    }
}

webpack.mix.js:

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/js').postCss('resources/css/app.css', 'public/css', [
    require('postcss-import'),
    // require('bootstrap'),
    require('tailwindcss'),
    require('autoprefixer'),
])
    .vue();

/*
* CK Editor Config
*/
const CKEditorWebpackPlugin = require( '@ckeditor/ckeditor5-dev-webpack-plugin' );
const CKEStyles = require('@ckeditor/ckeditor5-dev-utils').styles
const CKERegex = {
    svg: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
    css: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
}

Mix.listen('configReady', webpackConfig => {
    const rules = webpackConfig.module.rules;
    const targetSVG = /(\.(png|jpe?g|gif|webp)$|^((?!font).)*\.svg$)/;
    const targetFont = /(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/;
    const targetCSS = /\.css$/;

    // exclude CKE regex from mix's default rules
    for (let rule of rules) {
        if (rule.test.toString() === targetSVG.toString()) {
            rule.exclude = CKERegex.svg;
        }
        else if (rule.test.toString() === targetFont.toString()) {
            rule.exclude = CKERegex.svg;
        }
        else if (rule.test.toString() === targetCSS.toString()) {
            rule.exclude = CKERegex.css;
        }
    }
});

/**
 * Webpack Config for CK Editor
 */
mix.webpackConfig({
    plugins: [
        new CKEditorWebpackPlugin({
            language: 'en'
        })
    ],
    module: {
        rules: [
            {
                test: CKERegex.svg,
                use: ['raw-loader']
            },
            {
                test: CKERegex.css,
                use: [
                    {
                        loader: 'postcss-loader',
                        options: {
                            postcssOptions: CKEStyles.getPostCssConfig({
                                themeImporter: {
                                    themePath: require.resolve('@ckeditor/ckeditor5-theme-lark')
                                },
                                minify: true
                            })
                        }
                    }
                ]
            }
        ]
    }
})

Any ideas on what I'm doing wrong? There's not many examples or much documentation on how to use CKEditor 5 with Laravel and Vue.

kicker10BOG commented 2 years ago

Just figured it out... Think I had it this way earlier, but since it gave another error, I eventually got stuck on this after trying to solve the original issue, which I'm still struggling with.

Anyways, the fix for this issue is to change the component to the one I have commented out above (ckeditor: CKEditor.component) and change the tag to ckeditor