javascriptvue.jsprintingvuejs3vue-cli-4

How to print a specific element in Vue 3?


I'm working on a project where I want the functionallity to print a specific element of my page. There is a mixin/plugin called VueHtmlToPaper that does exactly what I want but I have trouble importing it into my Vue 3 CLI project since it was created for VueJS2 and the global API is different. Any help is appreciated.

main.js

import { createApp } from 'vue'

import App from './App.vue'

 createApp(App).mount('#app')

Project structure :

enter image description here


Solution

  • Since this plugin is not compatible with vue 3, we could do our plugin based on vue-html-to-paper plugin :

    1. create a folder called plugins in project root then inside it add VueHtmlToPaper.js file with the following content :
    
    function addStyles(win, styles) {
        styles.forEach((style) => {
          let link = win.document.createElement("link");
          link.setAttribute("rel", "stylesheet");
          link.setAttribute("type", "text/css");
          link.setAttribute("href", style);
          win.document.getElementsByTagName("head")[0].appendChild(link);
        });
      }
      
      const VueHtmlToPaper = {
        install(app, options = {}) {
          app.config.globalProperties.$htmlToPaper = (
            el,
            localOptions,
            cb = () => true
          ) => {
            let defaultName = "_blank",
              defaultSpecs = ["fullscreen=yes", "titlebar=yes", "scrollbars=yes"],
              defaultReplace = true,
              defaultStyles = [];
            let {
              name = defaultName,
              specs = defaultSpecs,
              replace = defaultReplace,
              styles = defaultStyles
            } = options;
      
            // If has localOptions
            // TODO: improve logic
            if (!!localOptions) {
              if (localOptions.name) name = localOptions.name;
              if (localOptions.specs) specs = localOptions.specs;
              if (localOptions.replace) replace = localOptions.replace;
              if (localOptions.styles) styles = localOptions.styles;
            }
      
            specs = !!specs.length ? specs.join(",") : "";
      
            const element = window.document.getElementById(el);
      
            if (!element) {
              alert(`Element to print #${el} not found!`);
              return;
            }
      
            const url = "";
            const win = window.open(url, name, specs, replace);
      
            win.document.write(`
              <html>
                <head>
                  <title>${window.document.title}</title>
                </head>
                <body>
                  ${element.innerHTML}
                </body>
              </html>
            `);
      
            addStyles(win, styles);
      
            setTimeout(() => {
              win.document.close();
              win.focus();
              win.print();
              win.close();
              cb();
            }, 1000);
      
            return true;
          };
        }
      };
      
      export default VueHtmlToPaper;
      
    

    I just copied/pasted this code and I replaced Vue by app, then import it in main.js :

    import { createApp } from 'vue'
    
    import App from './App.vue'
    
     import  VueHtmlToPaper from './plugins/VueHtmlToPaper'
    
    let app=createApp(App);
    
     app.use(VueHtmlToPaper)
    
     app.mount('#app')
    

    then use it in any component like :

    <template>
    <div class="home">
        <img alt="Vue logo" src="../assets/logo.png">
    
        <!-- SOURCE -->
        <div id="printMe">
            <h1>Print me!</h1>
        </div>
        <!-- OUTPUT -->
        <button @click="print">print</button>
    
    </div>
    </template>
    
    <script lang="ts">
    import {
        defineComponent
    } from 'vue';
    import HelloWorld from '@/components/HelloWorld.vue'; /
    
    export default defineComponent({
        name: 'Home',
        components: {
            HelloWorld,
        },
        methods: {
            print() {
                this.$htmlToPaper('printMe')
            }
        },
        mounted() {
    
        }
    });
    </script>
    
    

    LIVE DEMO