emilianotisato / nova-tinymce

Laravel Nova TinyMCE editor (with images upload capabilities!)
MIT License
116 stars 39 forks source link

help to add a custom button on the toolbar #60

Open pcorrick opened 3 years ago

pcorrick commented 3 years ago

I'm porting a Laravel app from Voyager (https://github.com/the-control-group/voyager) to Nova. I have a custom javascript function tinymce_setup_callback(editor) in my Voyager app that creates a toolbar button for TinyMCE, but I'm having some trouble replicating it in Nova.

I've tried editing the FormField.vue component to run this.loaded method onInit, but the button doesn't appear. In my options array I have:

'toolbar' => 'mybutton | undo redo | styleselect | bold italic',

I know the loaded method runs because if I use editor.addButton I get an error in the console:

Error: editor.addButton has been removed in tinymce 5x, use editor.ui.registry.addButton

I expect the loaded method is running the tinymce component is initialised so it's too late to add the button but I can't figure out how to get it in there during init/setup.

<template>
    <default-field :field="field" :full-width-content="true" :show-help-text="showHelpText">
        <template slot="field">
            <editor :id="field.id || field.attribute"
                    v-model="value"
                    :class="errorClasses"
                    :placeholder="field.name"
                    :init="options"
                    v-on:onInit="this.loaded"
            ></editor>
            <p v-if="hasError" class="my-2 text-danger">
                {{ firstError }}
            </p>
        </template>
    </default-field>
</template>
    methods: {

        loaded: function (event, editor) {
            // tiny has loaded, now say we are loaded
            // update the editor
            this.editor = editor;
            editor.ui.registry.addButton('mybutton', {
                text: "Insert Text",
                type: "menubutton",
                icon: false,
                menu: [{
                    text: 'Some text',
                    onclick: function() { editor.insertContent('Some text'); }
                }]
            })
        },
pcorrick commented 3 years ago

Ok so I got it working but it's a bit of a hack. The editor now uses initObj returned by the data function, which joins the setup function with the options array.

I also had to change onclick to onAction (new in TinyMCE v5).

I'm not sure if there is a way to put the setup function in the options array from my Nova resource.

<template>
    <default-field :field="field" :full-width-content="true" :show-help-text="showHelpText">
        <template slot="field">
            <editor :id="field.id || field.attribute"
                    v-model="value"
                    :class="errorClasses"
                    :placeholder="field.name"
                    :init="initObj"
            ></editor>
export default {

    data () {
        let options = this.field.options
        return {
            initObj: {
                setup: function (editor) {
                    editor.ui.registry.addButton('mybutton', {
                        text: "Insert Text",
                        onAction: function () {
                            editor.insertContent('&nbsp;<b>It\'s my button!</b>&nbsp;');
                        }
                    });
                },
                ...options
            }
        }
    },