Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printing elements with VueJS using 3rd party libraries

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

like image 339
manish thakur Avatar asked Dec 16 '19 06:12

manish thakur


2 Answers

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

like image 70
ux.engineer Avatar answered Oct 11 '22 23:10

ux.engineer


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

like image 33
arkuuu Avatar answered Oct 11 '22 22:10

arkuuu