Guide to displaying a particular item in Vue 3

Currently, I am embarking on a project that requires the functionality to print a specific element of my webpage. After some research, I came across a mixin/plugin known as VueHtmlToPaper which seems to be the perfect solution for what I need. However, I am facing some challenges when trying to import it into my Vue 3 CLI project since it was originally designed for VueJS2 and the global API has changed. Any assistance or guidance on how to successfully integrate this plugin would be greatly appreciated.

main.js

import { createApp } from 'vue'

import App from './App.vue'

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

Project structure :

https://i.sstatic.net/tguB7.png

Answer №1

If you're facing compatibility issues with Vue 3 for a specific plugin, one alternative is to create your own plugin based on vue-html-to-paper:

  1. To begin, make a new folder named 'plugins' in the project root directory. Inside this folder, add a file called VueHtmlToPaper.js with the code provided below:

// Custom function to add styles to the document
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
      ) => {
        // Default settings
        let defaultName = "_blank",
          defaultSpecs = ["fullscreen=yes", "titlebar=yes", "scrollbars=yes"],
          defaultReplace = true,
          defaultStyles = [];
          
        let {
          name = defaultName,
          specs = defaultSpecs,
          replace = defaultReplace,
          styles = defaultStyles
        } = options;
  
        // Checking for local options and updating if present
        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;
  

To integrate this custom plugin into your project, simply copy the code, replace instances of Vue with app, and then import it in the 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')

You can now use this plugin in any component like so:

<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>

Check out the LIVE DEMO for a working example.

Answer №2

To avoid pop-up windows, I utilized an iframe instead of a window in VueHtmlToPaper.js

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 
          defaultStyles = [];
        let {
          styles = defaultStyles
        } = options;
  
        
        if (localOptions) {
          if (localOptions.styles) styles = localOptions.styles;
        }
  
        const element = window.document.getElementById(el);
  
        if (!element) {
          alert(`Element to print #${el} not found!`);
          return;
        }
  
        var ifprint = document.createElement("iframe");
        document.body.appendChild(ifprint);
        ifprint.setAttribute("style","height:0;width:0;");

        const win = ifprint.contentWindow;
  
        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();
          document.body.removeChild(ifprint);
          cb();
        }, 1);
  
        return true;
      };
    }
  };
  
  export default VueHtmlToPaper;

Answer №3

If you're looking to print specific content, I've created a Vue 3 component called vue-to-print. Feel free to give it a go!

  1. To get started, simply install it using npm install vue-to-print --save.
  2. Assuming the content you want to print is as follows:
    <div ref="componentRef">
      some printed content
    </div>
    
  3. Use the handlePrint function that is returned by useVueToPrint to actually print the content:
    import { useVueToPrint } from "vue-to-print";
    
    const { handlePrint } = useVueToPrint({
      content: () => componentRef.value,
      documentTitle: "AwesomeFileName",
    });
    
    handlePrint();
    

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Live AJAX inquiries in progress

Is there a way to track the number of active AJAX requests in jQuery, Mootools, or another library similar to Prototype's Ajax.activeRequestCount? I am looking for a method that can be used across different libraries or directly through XMLHttpRequest ...

Matching an element that contains a specific string in JS/CSS

I'm currently faced with an HTML file that's being generated by an outdated system, making it tricky for me to control the code generation process. The structure of the HTML code is as follows: <table cellpadding=10> <tr> ...

Learn how to display every ASCII or EBCDIC character once radio buttons have been selected

I'm currently working on a simple website that requires the user to input a minimum of 256 characters, choose between ASCII or EBCDIC for conversion, and then click the submit button (Run) to display the final converted result on the page. However, I& ...

Ways to implement a scrollable v-list component using Vuetify

I have set up a v-list using flex layout, where the v-list expands to fill the remaining space horizontally in a column. However, if the list contains many elements with a total height that exceeds the column's height, the list ends up sticking out of ...

N8N: Deleting JSON Key from Output

Is it possible to remove the json key in my output file? I am unsure of the best approach to achieve this. I would like to return an array of data with all values, not just one value. If you want more information, here is a link to my N8N post: Manipulate ...

Children can easily access multiple items within a list by using the ul tag

I am struggling with changing the class of ul inside the ul.navigator. I want to change it only when I click on a particular li, but my current approach doesn't seem to be working. Can anyone provide some guidance or assistance? $('.navigator& ...

Handling every promise in an array simultaneously

I am facing a problem with my array inside Promise.all. When I try to execute a function for the last iteration of forEach loop, I notice that my count_answers variable is only being set for the last object. This can be seen in the log output; the count_an ...

Encountering a ReferenceError: require is undefined error when utilizing contextIsolation: true in conjunction with a preload script

My goal is to implement a select folder popup functionality, and I have written the following code for this purpose. Within the create-window.ts file, I have included these browserOptions.webPreferences: webPreferences: { nodeIntegration: true, conte ...

obtain every potential substring in sequence

After exploring various methods to find possible substrings, I attempted an approach in PHP which can be found here. However, I have specific requirements for generating substrings. For example, if the input string is 'ABCDE', the desired combin ...

How can you iterate over the input elements that are currently visible within a form using Javascript?

Is there a way to clear the values of all visible input fields in a form using JavaScript? I'm currently struggling with setting text inputs to empty as they come out as undefined. Any suggestions on how to achieve this? ...

Conceal an item if it is located past a certain point (from the viewpoint of the camera)

In the realm of three-dimensional space, imagine a cube represented by a THREE.Mesh that has been added to the scene. cube.position.set( 10, 10, 10 ); scene.add( cube ); Once you have rotated the scene using your mouse, the goal is to cleverly conceal th ...

Is it possible for a property to be null or undefined on class instances?

Consider this TypeScript interface: export interface Person { phone?: number; name?: string; } Does having the question mark next to properties in the interface mean that the name property in instances of classes implementing the interface ca ...

How can I dynamically assign ngModel in AngularJS?

I've created a directive with an isolate scope that maps a list of objects to inputs for modifying a specific property. However, I now aim to make this component more universal by allowing it to bind to deeply nested properties within each object. Fo ...

When accessing nested objects in Props in Vue.js, an error may occur if the property of null/undefined

When I make an axios call, I receive an object which I pass to a child component. However, when I attempt to loop through the object in the child component to access a property of another nested object, I encounter an issue where the property is showing as ...

What is the best way to incorporate this HTML and script into a React component?

After receiving the embedded HTML and script from a platform, I discovered that a button triggers the script. It was originally designed to be embedded on a website, but I am attempting to integrate it into a React application. Here is the code provided fo ...

`There was an error in require.js stating that the property '$' of object #<Object> is not a function.`

Recently, I decided to give require.js a try for the first time, but unfortunately, I encountered an error that left me puzzled: Uncaught TypeError: Property '$' of object # is not a function. require.config({ shim: { "jquery" ...

Using moment.js to perform addition of time does not yield the desired outcome

Every time I try to ---- make changes ---- var someMoment = moment('6:30 PM', ["h:mm A"]); ---- end changes ---- someMoment.add(30, 'minutes') I am not getting any desired outcome. console.log(start); -- Moment {_isAMomentObject: ...

In Vue 3, the old and new values returned by a deep watcher are consistently the same

const app = { data(){ return { form: { name: '', password: '' } } }, watch: { form: { handler(form, oldForm){ console.log(form, oldForm); }, deep: true } } ...

What is the best way to define the active <li> tab using JQuery?

Initially, my HTML code includes a set of <li> elements that I want to dynamically add to the existing <ul>. <ul class="tabs" id="modal_addquestion_ul"> <li class="tab-link current" data-tab="multipleChoice">Multiple Choice< ...

Achieve self within a dynamically loaded module

I recently followed a tutorial on creating a dynamic sidebar toggle using Vue and Vuex, which you can access here. However, I encountered an issue with implementing a "close" button within the sidebar component. It seems that I cannot access 'this.co ...