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

DOC: Vue3.2 composition example + suggestion #220

Open
WilliamStam opened this issue Sep 6, 2022 · 1 comment
Open

DOC: Vue3.2 composition example + suggestion #220

WilliamStam opened this issue Sep 6, 2022 · 1 comment

Comments

@WilliamStam
Copy link

hi, LOVE the size of this library.

first lets get the suggestion out of the way. since the library has an init wont it make sense to have an "update" method as well? basicaly a wrapper for instance.content.innerHTML = 'new value' just to keep consitent?


for vue3.2 im using this and it seems to work ok

EditorComponent.vue

<template>
    <div ref="editor"></div>
</template>
<script setup>
import {
    ref,
    computed,
    reactive,
    onMounted,
    watch
} from "vue";
import pell from 'pell'

const props = defineProps(["modelValue"]);
const emits = defineEmits(["update:modelValue"]);
const editor = ref(null);
let last_value = null;

const content = computed({
    get(){
        return props.modelValue
    },
    set(value){
        // we emit the value back up to the parent component
        emits("update:modelValue",value);
        // need to know when to fire off thew watcher. dont want it updating the content with every char typed
        last_value = value
    }
})

onMounted(()=>{
    editor.value = pell.init({
      element: editor.value,
      onChange: html => {
          content.value = html
      },
      actions: [
        'bold',
        'italic',
        'underline',
        'strikethrough',
        'heading1',
        'heading2',
        'paragraph',
        'quote',
        'olist',
        'ulist',
        'code',
        'line',
      ]
    })
   // setting the initial values. not sure if they both needed but here goes
    editor.value.content.innerHTML = content.value
    last_value = content.value
})

watch(content,(to)=>{
    // while typing we dont want the watcher to keep updating the value since that keep jumping our cursor to the begining
    if (to != last_value){
        editor.value.content.innerHTML = to
    }
})
</script>

and usage

<template>
    <EditorComponent v-model="content"></EditorComponent>

    <div>
        <!-- the value of the editor is reactive -->
        <pre>
            {{ content }}
         </pre>
         <!-- We can then update the contents from here-->
         <button @click="content = `<div><strong>strong</strong> <em>em</em> <p>para</p> <hr></div>`">set value</button>
    </div>
</template>

<script setup>
import EditorComponent from "@/components/form/EditorComponent.vue";
import {
    ref,
} from "vue";
const content = ref(`<b>initial content</b>`);
</script>
@WilliamStam
Copy link
Author

New version time, This brings in being able to add a class / style dynamically to the content area (min-height etc)

EditorComponent.vue

<template>
    <div ref="editor" class="editor-area"></div>
</template>
<script setup>
import {
    ref,
    computed,
    reactive,
    onMounted,
    watch
} from "vue";
import pell from "pell";

const props = defineProps([
    "modelValue",
    "style",
    "class"
]);
const emits = defineEmits(["update:modelValue"]);
const editor = ref(null);
let last_value = null;
const content = computed({
    get() {
        return props.modelValue;
    },
    set(value) {
        emits("update:modelValue", value);
        last_value = value;
    }
});

const classes = {
    actionbar: "editor-nav",
    button: "editor-btn btn",
    content: "editor-content form-control",
    selected: "editor-btn-selected"
};

onMounted(() => {
    editor.value = pell.init({
        element: editor.value,
        onChange: html => {
            content.value = html;
        },
        actions: [
            "bold",
            "italic",
            "underline",
            "strikethrough",
            // "heading1",
            // "heading2",
            // "paragraph",
            // "quote",
            "olist",
            "ulist",
            // "code",
            "line",
        ],
        classes: Object.assign({}, classes, {content: classes.content + " " + props.class})
    });
    editor.value.content.innerHTML = content.value;
    last_value = content.value;

});

watch(content, (to) => {
    if (to != last_value) {
        editor.value.content.innerHTML = to;
    }
});


const styles = ref(props.style);
const watch_classes = computed(() => props.class);
watch(watch_classes, (to) => {
    editor.value.getElementsByClassName("editor-content")[0].className = classes.content + " " + to;
});
const watch_styles = computed(() => props.style);
watch(watch_styles, (to) => {
    editor.value.getElementsByClassName("editor-content")[0].style.cssText = to;
});

</script>

usage

<EditorComponent v-model="content"  :class="classes" :style="styles"></EditorComponent>

<button @click.prevent="classes = `bg-warning`">Set class .bg-warning</button>
<button @click.prevent="classes = `bg-danger`">Set class .bg-danger</button>
<button @click.prevent="styles = `min-height:600px;`">Set style min-height to 600</button>
 <button @click.prevent="styles = `min-height:300px; background:purple;`">Set style min-height to 300 and background to purple</button>
<button @click.prevent="styles=null; classes=null">Reset </button>

...

const classes = ref(null);
const styles = ref(null);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant