vue-froala-wysiwyg icon indicating copy to clipboard operation
vue-froala-wysiwyg copied to clipboard

Froala v3 not showing toolbar buttons

Open rolfo85 opened this issue 5 years ago • 9 comments

Hi,

I have updated the Froala Vue to the last version 3.0.0-rc.2-1 and there is something weird. I only see just few buttons on the toolbar.

See screenshot: https://i.imgur.com/xMkVxdS.png

In addition there isn't even the quickInsertButtons when creating a new line. I have a configuration with many things setup from the previous version, I tried to delete it and leave just the plain editor but the result is the screenshot I have attached. So it is not my config (which worked perfectly fine on the previous version).

HERE A SANDBOX THAT SHOWS THE PROBLEM: https://codesandbox.io/s/vue-froala-s6lie

Whereas the regular Froala version (without VUE) is working properly

rolfo85 avatar Jun 10 '19 00:06 rolfo85

It's same for me.

HighQualityCode avatar Jun 16 '19 19:06 HighQualityCode

The same for me :(

Rainbowm avatar Jun 17 '19 13:06 Rainbowm

I have had installed froala-editor 3.0.0 additional to vue-froala-wysiwyg 3.0.0. After removing both in vue cli and just installing vue-froala-wysiwyg it worked.

Additional info: Froala might have a problem running in a sandbox

benjamin79 avatar Jun 18 '19 08:06 benjamin79

No it doesn't work.

HighQualityCode avatar Jun 18 '19 14:06 HighQualityCode

I found the mistake. The new version is more modular and you have to insert the required plugins. e.g .: import 'froala-editor/css/froala_editor.pkgd.min.css'; import 'froala-editor/css/froala_style.min.css'; import 'froala-editor/js/plugins.pkgd.min.js';

or the specialisied plugins: import 'froala-editor/js/froala_editor.pkgd.min.js' import 'froala-editor/js/plugins/link.min.js' import 'froala-editor/js/plugins/image.min.js'

Rainbowm avatar Jun 20 '19 11:06 Rainbowm

Hi @Rainbowm , thanks it's working. 👍

HighQualityCode avatar Jun 20 '19 14:06 HighQualityCode

I've so far tried dozens of plugins and none work:

  // Froala.
  import VueFroala from 'vue-froala-wysiwyg/dist/vue-froala.min.js'
  import 'froala-editor/css/froala_editor.pkgd.min.css'
  import 'froala-editor/js/plugins.pkgd.min.js'
  import 'froala-editor/js/plugins/link.min.js'
  import 'froala-editor/js/plugins/lists.min.js'

Whether I include as above, or as <link> and <script> tags makes no difference.

OctaneInteractive avatar Aug 12 '19 20:08 OctaneInteractive

If anyone is stuck after the solutions above, the issue for us was importing the JS file after following the instructions above.

Where ever your calling import VueFroala from 'PATH/FILE' try to resolve that path, and if that doesn't work just create a file in the same folder as the file you are calling that and paste the following in the file for a quick fix. Hope this helps, I was stuck on this one for awhile.

` import FroalaEditor from "froala-editor"; export default (Vue, Options = {}) => { FroalaEditor.DefineIcon("alert", { NAME: "info", SVG_KEY: "help" }); FroalaEditor.RegisterCommand("alert", { title: "Hello", focus: false, undo: false, refreshAfterCallback: false, callback: function() { alert("Hello!"); } }); var froalaEditorFunctionality = { props: ["tag", "value", "config", "onManualControllerReady"],

    watch: {
        value: function() {
            this.model = this.value;
            this.updateValue();
        }
    },

    render: function(createElement) {
        return createElement(this.currentTag, [this.$slots.default]);
    },

    created: function() {
        this.currentTag = this.tag || this.currentTag;
        this.model = this.value;
    },

    // After first time render.
    mounted: function() {
        if (this.SPECIAL_TAGS.indexOf(this.currentTag) != -1) {
            this.hasSpecialTag = true;
        }

        if (this.onManualControllerReady) {
            this.generateManualController();
        } else {
            this.createEditor();
        }
    },

    beforeDestroy: function() {
        this.destroyEditor();
    },

    data: function() {
        return {
            initEvents: [],

            // Tag on which the editor is initialized.
            currentTag: "div",

            // Editor element.
            _editor: null,

            // Current config.
            currentConfig: null,

            // Editor options config
            defaultConfig: {
                immediateVueModelUpdate: false,
                vueIgnoreAttrs: null
            },

            editorInitialized: false,

            SPECIAL_TAGS: ["img", "button", "input", "a"],
            INNER_HTML_ATTR: "innerHTML",
            hasSpecialTag: false,

            model: null,
            oldModel: null
        };
    },
    methods: {
        updateValue: function() {
            if (JSON.stringify(this.oldModel) == JSON.stringify(this.model)) {
                return;
            }

            this.setContent();
        },

        createEditor: function() {
            if (this.editorInitialized) {
                return;
            }

            this.currentConfig = this.config || this.defaultConfig;

            this.setContent(true);

            // Bind editor events.
            this.registerEvents();
            this.initListeners();

            this._editor = new FroalaEditor(this.$el, this.currentConfig);

            this.editorInitialized = true;
        },

        setContent: function(firstTime) {
            if (!this.editorInitialized && !firstTime) {
                return;
            }

            if (this.model || this.model == "") {
                this.oldModel = this.model;

                if (this.hasSpecialTag) {
                    this.setSpecialTagContent();
                } else {
                    this.setNormalTagContent(firstTime);
                }
            }
        },

        setNormalTagContent: function(firstTime) {
            var self = this;

            function htmlSet() {
                self._editor.html.set(self.model || "");

                //This will reset the undo stack everytime the model changes externally. Can we fix this?

                self._editor.undo.saveStep();
                self._editor.undo.reset();
            }

            if (firstTime) {
                this.registerEvent("initialized", function() {
                    htmlSet();
                });
            } else {
                htmlSet();
            }
        },

        setSpecialTagContent: function() {
            var tags = this.model;

            // add tags on element
            if (tags) {
                for (var attr in tags) {
                    if (tags.hasOwnProperty(attr) && attr != this.INNER_HTML_ATTR) {
                        this.$el.setAttribute(attr, tags[attr]);
                    }
                }

                if (tags.hasOwnProperty(this.INNER_HTML_ATTR)) {
                    this.$el.innerHTML = tags[this.INNER_HTML_ATTR];
                }
            }
        },

        destroyEditor: function() {
            if (this._editor) {
                this._editor.destroy();
                this.editorInitialized = false;
                this._editor = null;
            }
        },

        getEditor: function() {
            return this._editor;
        },

        generateManualController: function() {
            var controls = {
                initialize: this.createEditor,
                destroy: this.destroyEditor,
                getEditor: this.getEditor
            };

            this.onManualControllerReady(controls);
        },

        updateModel: function() {
            var modelContent = "";

            if (this.hasSpecialTag) {
                var attributeNodes = this.$el[0].attributes;
                var attrs = {};

                for (var i = 0; i < attributeNodes.length; i++) {
                    var attrName = attributeNodes[i].name;
                    if (
                        this.currentConfig.vueIgnoreAttrs &&
                        this.currentConfig.vueIgnoreAttrs.indexOf(attrName) != -1
                    ) {
                        continue;
                    }
                    attrs[attrName] = attributeNodes[i].value;
                }

                if (this.$el[0].innerHTML) {
                    attrs[this.INNER_HTML_ATTR] = this.$el[0].innerHTML;
                }

                modelContent = attrs;
            } else {
                var returnedHtml = this._editor.html.get();
                if (typeof returnedHtml === "string") {
                    modelContent = returnedHtml;
                }
            }

            this.oldModel = modelContent;
            this.$emit("input", modelContent);
        },

        initListeners: function() {
            var self = this;

            this.registerEvent("initialized", function() {
                if (self._editor.events) {
                    // bind contentChange and keyup event to froalaModel
                    self._editor.events.on("contentChanged", function() {
                        self.updateModel();
                    });

                    if (self.currentConfig.immediateVueModelUpdate) {
                        self._editor.events.on("keyup", function() {
                            self.updateModel();
                        });
                    }
                }
            });
        },

        // register event on editor element
        registerEvent: function(eventName, callback) {
            if (!eventName || !callback) {
                return;
            }

            // Initialized event.
            if (eventName == "initialized") {
                this.initEvents.push(callback);
            } else {
                if (!this.currentConfig.events) {
                    this.currentConfig.events = {};
                }

                this.currentConfig.events[eventName] = callback;
            }
        },

        registerEvents: function() {
            // Handle initialized on its own.
            this.registerInitialized();

            // Get current events.
            var events = this.currentConfig.events;

            if (!events) {
                return;
            }

            for (var event in events) {
                if (events.hasOwnProperty(event) && event != "initialized") {
                    this.registerEvent(event, events[event]);
                }
            }
        },

        registerInitialized: function() {
            // Bind initialized.
            if (!this.currentConfig.events) {
                this.currentConfig.events = {};
            }

            // Set original initialized event.
            if (this.currentConfig.events.initialized) {
                this.registerEvent(
                    "initialized",
                    this.currentConfig.events.initialized
                );
            }

            // Bind initialized event.
            this.currentConfig.events.initialized = () => {
                for (var i = 0; i < this.initEvents.length; i++) {
                    this.initEvents[i].call(this._editor);
                }
            };
        }
    }
};

Vue.component("Froala", froalaEditorFunctionality);

var froalaViewFunctionality = {
    props: ["tag", "value"],

    watch: {
        value: function(newValue) {
            this._element.innerHTML = newValue;
        }
    },

    created: function() {
        this.currentTag = this.tag || this.currentTag;
    },

    render: function(createElement) {
        return createElement(this.currentTag, {
            class: "fr-view"
        });
    },

    // After first time render.
    mounted: function() {
        this._element = this.$el;

        if (this.value) {
            this._element.innerHTML = this.value;
        }
    },

    data: function() {
        return {
            currentTag: "div",
            _element: null
        };
    }
};

Vue.component("FroalaView", froalaViewFunctionality);

};

`

briansackett avatar Dec 19 '19 16:12 briansackett

Thanks for your answers. I have been trying trying trying but all toolbuttons aren't shown. Just default buttons such as "Bold" are shown. Could you please help me? The following codes are what I used in my react project.

import 'froala-editor/css/froala_style.min.css'; import 'froala-editor/css/froala_editor.pkgd.min.css'; import FroalaEditor from 'react-froala-wysiwyg'; import 'froala-editor/js/plugins.pkgd.min';

mavsin avatar Oct 14 '21 23:10 mavsin