Search code examples
javascriptcssvue.jswysiwyg

Add CSS rules from textarea using v-html


I am building a WYSIWYG type application where a user can write CSS in a textarea and that CSS rule will be applied to the HTML on page i tried something like this in template

<textarea v-bind="css"></textarea>
<style v-html="css"></style>

VueCompilerError: Tags with side effect ( and ) are ignored in client component templates.


Solution

  • Old answer, below is better one

    Add textarea with v-model:

    <textarea v-model="css" />
    

    You can create style tag in onMounted hook:

    onMounted(() => {
      const style = document.createElement("style");
      style.type = "text/css";
      updateCss(style, css.value);
    
      document.getElementsByTagName("head")[0].appendChild(style);
    
      el.value = style;
    });
    

    You must be able to access this element later, so assign style to el.value.

    Then add watch on input value:

    watch(css, () => {
      updateCss(el.value, css.value);
    });
    

    Where updateCss is a function:

    const updateCss = (el, css) => {
      if (el.styleSheet) {
        el.styleSheet.cssText = css.value;
      } else {
        el.innerHTML = "";
        el.appendChild(document.createTextNode(css));
      }
    };
    

    Demo:

    https://codesandbox.io/s/cocky-mestorf-uqz6f?file=/src/App.vue:246-463

    Edit

    I found much better solution:

    <template>
      <textarea v-model="css" />
      <component :is="'style'" type="text/css" v-text="css"></component>
    </template>
    
    <script>
    import { ref } from "vue";
    export default {
      setup() {
        const css = ref("body { background-color: blue; }");
        return { css };
      },
    };
    </script>
    

    Component doesn't throw the error about style tag:

    <component :is="'style'">
    

    Note that there is v-text instead v-html. V-html could be unsafe.

    Demo: https://codesandbox.io/s/festive-germain-q9tg3?file=/src/App.vue:122-281