13

I am working on HTML table and and printing that table to printer using html-to-paper in vue.js,What I am doing is on click of add creating a new row and then on click of print I am trying to print the table but it is not taking any data only showing empty cells

Code App.vue

    <template>
  <div id="app">
    <button type="button" @click="btnOnClick">Add</button>

    <div id="printMe">
      <table class="table table-striped table-hover table-bordered mainTable" id="Table">
    <thead>
      <tr>

        <th class="itemName">Item Name</th>
        <th>Quantity</th>
        <th>Selling Price</th>
        <th>Amount</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(tableData, k) in tableDatas" :key="k">

        <td>
          <input class="form-control" readonly v-model="tableData.itemname" />
        </td>
        <td>
          <input class="form-control text-right" type="text" min="0" step=".01" v-model="tableData.quantity" v-on:keyup="calculateQty(tableData)" />
        </td>
        <td>
          <input class="form-control text-right" type="text" min="0" step=".01" v-model="tableData.sellingprice" v-on:keyup="calculateSPrice(tableData)" />
        </td>
        <td>
          <input readonly class="form-control text-right" type="text" min="0" step=".01" v-model="tableData.amount" />
        </td>
      </tr>
    </tbody>
  </table>
    </div>
    <button @click="print">Print</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableDatas: []
    }

  },
  methods: {
    btnOnClick(v) {
      this.tableDatas.push({
        itemname: "item",
        quantity: 1,
        sellingprice: 55,
        amount: 55
      });
    },
     print() {
      this.$htmlToPaper('printMe');
    }
  }
};
</script>

<style>
</style>

main.js

 import Vue from "vue";
import App from "./App.vue";
import VueHtmlToPaper from "vue-html-to-paper";

Vue.config.productionTip = false;
Vue.use(VueHtmlToPaper);

new Vue({
  render: h => h(App)
}).$mount("#app");

here the working code in codesandbox

Please check running code

Edit as per bounty

i have to do it with 'html-to-paper' the issue is I am not able to give style to my elements for printing using @media print

  • The answer by ux.engineer is fine but causing browser issue crome and firefox are blocking it due to security isssue

Please check code sandbox for example here is my full code, i am trying to give styling but not happening

  • The html-to-print plugin uses window.open so when I am clicking on print it is not taking the the style to new page.
  • That is where I am stuck as why it is not taking media style, how can I override my style on window.open

I was Using print-nb But it is not working on browser due to some security reason this is what is says while using print-nb

ux.engineer
  • 10,082
  • 13
  • 67
  • 112
manish thakur
  • 760
  • 9
  • 35
  • 76

3 Answers3

11

Unfortunately you cannot leverage Vue's data binding with this mycurelabs/vue-html-to-paper mixin package, as stated here by the package author.

However, I've created a workaround for by switching the package used here to Power-kxLee/vue-print-nb directive.

Here's a working example: https://codesandbox.io/s/kind-hypatia-inutd

PS. Choosing between similar packages may be tricky at times. One should evaluate the repo's usage and activity stats like: Used by, Watch, and Start on the front page, then check Open / Closed issues and Active / Closed Pull Requests, and then go to Insights to check Pulse (1 month), and Code Frequency.

Between these two, I would choose vue-print-nb for being more popular and actively used. Also because I'd prefer using a directive over a mixin.

As far as the other answer goes, keeping to use vue-html-to-paper for this purpose would need that kind of a hacky solution... Where as this directive works out-of-the-box.

https://github.com/mycurelabs/vue-html-to-paper

https://github.com/Power-kxLee/vue-print-nb

ux.engineer
  • 10,082
  • 13
  • 67
  • 112
  • 1
    I don't know how this printing packages compare, but if it's ok to switch packages I think this is a better solution than my workaround with placeholders. – arkuuu Dec 18 '19 at 09:23
  • @ux.engineer as I found your Idea as very simple and clean,I ha a doubt (issue) here when I am printing the table it is printing full page with `inputs` inside which is not good, I want to remove that input and be it like normal field, also can I manage height,because I am using `USB Printer` which is not having a4 sheets. – manish thakur Dec 19 '19 at 05:41
  • @manishthakur you can use global CSS styling with media query targeting print, here's a working example: https://codesandbox.io/s/ecstatic-fire-zo2b2 – ux.engineer Dec 19 '19 at 09:50
  • Ok it is working so by this I can define the cs, the issue is here suppose four rows are there, but the printer is printing full lengthy printer, i am using USB printer which are user to print bills, please clear this thing to me – manish thakur Dec 19 '19 at 10:07
  • @manishthakur how about this: https://codesandbox.io/s/charming-sound-7h1bg - using `@page` CSS-rule (https://developer.mozilla.org/en-US/docs/Web/CSS/@page) as explained here https://stackoverflow.com/questions/44064707/force-a5-paper-size-in-chromes-print-settings-css – ux.engineer Dec 19 '19 at 11:06
  • @ux.engineer Hey I was using your answer only but now running from my system the browser throws error I don't know why, the error is about security block of css, please check my Edit I have updated an Image of that – manish thakur Jan 09 '20 at 05:25
  • Thank you for posting about Power-kxLee/vue-print-nb but after installing it and running it on what I would consider a fairly simple application running in the browser, I discovered what I'm considering a major bug. It crashes when select elements don't have their option selected. I posted some sample code on the authors https://github.com/Power-kxLee/vue-print-nb/issues/132 five days ago but so far no reply. Now wondering if this is a project without public source code that is no longer being maintained. Also found timing issues with Chrome hanging when document.write() taking to long. – Harvey Mushman Nov 28 '21 at 21:08
6

As others have mentioned, this is not possible with the package you use, because the bound data from v-model doesn't exist when printing. So you need to get this data statically inside your html. Source

A Workaround would be to use input placeholders:

Add a reference to your table:

<tbody ref="tablebody">

This allows you to select this element in your method. Now change the print method:

print() {
  const inputs = this.$refs.tablebody.getElementsByTagName("input");
  for (let input of inputs) {
    input.placeholder = input.value;
  }
  this.$htmlToPaper("printMe");
  for (let input of inputs) {
    input.placeholder = "";
  }
}

Then maybe style the placeholders with css, because it looks grey by default.

I first tried to somehow reset the value of the input, like input.value = input.value, but unfortunately that didn't work.

Updated your code here

tony19
  • 125,647
  • 18
  • 229
  • 307
arkuuu
  • 619
  • 7
  • 23
  • 1
    A clever solution, although bit hacky. But seems needed if one would like to stick with using this particular Vue mixin for printing dynamic values like this. However at this point I'd look for alternative packages. – ux.engineer Dec 18 '19 at 09:28
  • @arkuuu Please check my edit part whenever you will be free. – manish thakur Jan 08 '20 at 11:52
  • @manishthakur I read it but I've no idea. Maybe you could include put your print css rules in a separate css file and use the `styles` option of vue-html-to-paper like you did with the other stylesheets. – arkuuu Jan 08 '20 at 14:12
  • 1
    I have tried that but nothing changed, still it is not taking styles – manish thakur Jan 09 '20 at 05:24
0

As per your new bounty on the question, for sticking to using vue-html-to-paper, here is an updated code example for loading externals stylesheet to the print window.

It first loads Bootstrap styles from an external CDN, then a local CSS file from the public directory. This local stylesheet has only one style for using !important override for input background color to green.

Chrome on Windows applies that green background style to inputs if print option background graphics is applied. Firefox on Windows has a different print options panel, which doesn't have such a setting.

Yet both are applying Bootstrap styles at least partly, so the stylesheets are loaded and in play.

This input background style issue was to demonstrate differences in how browsers handle print styles, and it's a wider topic outside the scope of this question.

PS. I'm not sure what kind of security issue there was with vue-print-nb package but perhaps it could be solved. You should open an issue in their Github repo with a minimal bug reproduction example.

Adding this answer as a separate entry if that vue-print-nb solution's issue gets solved later and my answer be updated.

ux.engineer
  • 10,082
  • 13
  • 67
  • 112
  • Hey I am checking it is not taking styles perfectly as I am trying to remove `input fields ` but it is taking all of them. – manish thakur Jan 16 '20 at 09:29
  • It's unclear which styles are you trying to apply... As said, styles don't come to print in same fashion than in the browser, as there are restrictions. And even those vary between the browsers / platforms. But the Bootstrap stylesheet *does get applied*, doesn't it? And my override, so styles are loaded? – ux.engineer Jan 16 '20 at 10:35
  • No I am removing the input fields but it is not removing, as I want to remove input field and show it as basich table with some style which I want to give on print i.e font size and alignment but it is not taking, I am hiding a column also but on print it is taking all of them – manish thakur Jan 16 '20 at 11:58
  • Hey Can you guess what is the issue with `print-nb` as that is the best one to work with but I don't know why browser not allowing css – manish thakur Jan 16 '20 at 11:59