I'm using vue-html2pdf to generate a pdf report. To avoid row breaking pagebreak: { mode: ["avoid-all", "css", "legacy"] } is used. However, a few of the columns of the generated report are growing vertically, and also making the rows to break in the report. How can this issue be fixed with auto pagebreak configuration?
Template
<template>
<div>
<VueHtml2pdf
:show-layout="false"
:float-layout="true"
:enable-download="true"
:preview-modal="true"
:paginate-elements-by-height="1300"
filename="ABCD-Report"
:pdf-quality="1"
pdf-format="a2"
pdf-orientation="landscape"
:html-to-pdf-options="htmlToPdfOptions"
pdf-content-width="2200px"
ref="html2Pdf"
#hasDownloaded="onDownload"
#beforeDownload="beforeDownload($event)"
>
<section slot="pdf-content">
<div style="margin: 30px">
<h2>Report Data:</h2>
<br />
<el-table :data="sampleData">
<el-table-column prop="instruction" label="Instruction">
</el-table-column>
<el-table-column prop="description" label="Description">
</el-table-column>
<el-table-column prop="reason" label="Reason">
</el-table-column>
<el-table-column
prop="documentation" label="Documentation">
</el-table-column>
<el-table-column prop="work" label="Work">
</el-table-column>
</el-table>
</div>
</section>
</VueHtml2pdf>
</div>
</template>
Script
<script>
import VueHtml2pdf from "vue-html2pdf";
export default {
name: "GenerateReportPdf",
components: { VueHtml2pdf },
data() {
return {
sampleData: null,
};
},
computed: {
htmlToPdfOptions() {
return {
margin: [0, 0],
filename: "ABCD-Report.pdf",
image: { type: "jpeg", quality: 1, format: "a2" },
html2canvas: { scale: 1, letterRendering: true },
jsPDF: {
unit: "pt",
format: "a2",
orientation: "landscape",
},
pagebreak: { mode: ["avoid-all", "css", "legacy"] },
};
},
},
methods: {
//methods added here to fetch the report data
},
};
</script>
Related
How to customize a select or another component like this design. I tried with v-select, BFormSelect, and others, the options are images or icons, and the output-
{
languages: {
en: {
title: "the text writted",
},
},
logo: "this logo in base64"
}
<template>
<div>
<div>
<b-form
ref="form"
class="repeater-form p-2"
#submit.prevent="repeateAgain"
>
<div>
<v-select
v-model="selected"
:options="options"
:multiple="false"
item-text="text"
item-value="value"
label="Select options"
>
<template slot="option" slot-scope="option">
<img :src="option.src" class="mr-2" style="width: 20px; height: 20px;"/>
{{ option.text }}
</template>
</v-select>
</div>
</b-form>
</div>
</div>
</template>
<script>
import {
BForm, BFormGroup, BFormInput, BRow, BCol, BButton, BFormCheckbox, BFormSelect, BDropdown
} from 'bootstrap-vue'
import vSelect from 'vue-select'
export default {
components: {
BForm,
BRow,
BCol,
BButton,
BFormGroup,
BFormInput,
BFormCheckbox,
BFormSelect,
vSelect,
BDropdown,
},
data() {
const typeOptions = ['include', 'not_include', 'important']
return {
typeOptions,
selected: [],
options: [
{
value: null,
text: "Please select some item",
src: ""
{
value: "b",
text: "Default Selected Option",
src: "../../../../assets/images/trip_icons/almuerzo.png"
},
{
value: "c",
text: "This is another option",
src: "../../../../assets/images/trip_icons/almuerzo.png"
},
{
value: "d",
text: "This one is disabled",
disabled: true,
src: "https://mdn.mozillademos.org/files/7693/catfront.png"
}
]
}
},
methods: {
select(option) {
console.log(option);
this.selected = option;
},
},
}
</script>
This is the result now but it is not enough, I hope to customize more.
So I have a datatable of images that I want to expand in an overlay tag on click.
To do that, I created an array for each column of the table and I mapped it to its corresponding image.
Here's the code :
<template>
<v-app>
<app-navbar />
<v-main>
<div class="text-center">
<h3>
test {{ $route.params.name }}, {{ $route.query.status }},{{
$route.query.tag
}}
</h3>
</div>
<v-data-table
:headers="headers"
:items="imagesref"
:items-per-page="5"
class="elevation-1"
>
<template v-slot:[`item.index`]="{ index }">
{{index+1}}
</template>
<template v-slot:[`item.ref`]="{ index }">
<v-img :src="imagesref[index]" max-width="750" max-height="750" #click="expref[index] = !expref[index]"/>
<v-overlay :value="expref[index]"><v-img :src="imagesref[index]" max-width="1300" max-height="900" #click="expref[index] = !expref[index]"/> </v-overlay>
</template>
<template v-slot:[`item.test`]="{ index }">
<v-img :src="imagestest[index]" max-width="750" max-height="750" #click="exptest[index] = !exptest[index]"/>
<v-overlay :value="exptest[index]"><v-img :src="imagestest[index]" max-width="1300" max-height="900" #click="exptest[index] = !exptest[index]"/> </v-overlay>
</template>
<template v-slot:[`item.res`]="{ index }">
<v-img :src="imagesresult[index]" max-width="750" max-height="750" #click="expres[index] = !expres[index]"/>
<v-overlay :value="expres[index]"><v-img :src="imagesresult[index]" max-width="1300" max-height="900" #click="expres[index] = !expres[index]"/> </v-overlay>
</template>
<template #[`item.Scrubber`]="{ index }">
<nuxt-link :to="{ path: 'scrubber', query: { imageref: imagesref[index],imagetest:imagestest[index],imageres:imagesresult[index] }}">Show Scrubber</nuxt-link>
</template>
</v-data-table>
</v-main>
</v-app>
</template>
<script>
import appNavbar from "../../../components/appNavbar.vue"
import axios from "axios"
export default {
components: { appNavbar },
name: "App",
data() {
return {
expref:[],
exptest:[],
expres:[],
items: [],
imagesref: [],
imagestest: [],
imagesresult: [],
headers: [
{ text: 'index',value: 'index',sortable:false},
{ text: 'Imagesref', value: 'ref',sortable:false },
{ text: 'Imagestest', value: 'test',sortable:false },
{ text: 'Imagesresult', value: 'res',sortable:false },
{ text: 'Scrubber', value: 'Scrubber',sortable:false },
]
}
},
async created() {
try {
const res = await axios.get(`http://localhost:3004/tests`, {
params: { name: this.$route.params.name },
})
this.items = res.data
this.imagesref = res.data[0].refimages
this.imagestest = res.data[0].testimages
this.imagesresult = res.data[0].resultimages
for (let i of this.imagesref){
this.expref.push(false);
this.exptest.push(false);
this.expres.push(false);
}
} catch (error) {
console.log(error)
}
}
}
</script>
<style scoped>
</style>
When I tested it, after I click on the image the corresponding variable in the array changes its value to true but the overlay is not getting displayed but somehow when I change the value manually on devtools it works.Does someone have any idea what's going on and how can i make it work ?
My first column (Test1) is active, so the background turns orange. Why does the active class not change to the second column (Test2) when I click the radio button?
I'd like it to change the active class when the radio button is clicked.
I have the following template:
<template v-if="columns" v-for="(item, index) in columns" v-bind="item">
<div class="card-container"
:style="{'height': item.height+'%'}"
:class="{ active: item.active}">
<div class="card-inner">
<input type="radio" v-if="item.selectedDefault" checked v-model="currentInput" name="cardRadioGroup"
:value="item.id" v-on:change="updateDetails(item, index)"/>
<input type="radio" v-else v-model="currentInput" name="cardRadioGroup" :value="item.id"
v-on:change="updateDetails(item, index)"/>
<template v-if="item.gbAmount === null">
Onbeperkt
</template>
<template v-else>
{{ item.gbAmount }} GB
</template>
{{ currentInput }}
</div>
</div>
</template>
With the following Vue code:
import {onMounted} from "vue";
export default {
name: 'Card',
components: {Details},
data() {
const columns =
{
"Test1": {
"id": 1,
"gbAmount": 0,
"price": 5,
"selectedDefault": false,
"informationGet": ["bla", "bla"],
"informationUsing": "Boop.",
"recommended": false,
"height": 16.66,
"active": true,
},
"Test2": {
"id": 2,
"gbAmount": 1,
"price": 10,
"selectedDefault": false,
"informationGet": ["beh", "beh"],
"informationUsing": "Beep",
"recommended": false,
"height": 33.33,
"active": false,
},
}
return {
columns,
currentColumn: {},
checkedCard: [],
currentInput: null,
};
},
methods: {
updateDetails(item, index) {
this.currentColumn = {
...item,
name: index,
active: true,
}
console.log($(this.currentColumn));
},
},
setup() {
return {};
},
};
And CSS:
.active {
background: orange;
}
You update this.currentColumn but in template use this.columns. Correct will be:
updateDetails(item, index) {
Object.keys(this.columns).forEach(key => this.columns[key].active = false);
this.columns[index].active = true;
console.log(this.columns);
}
<template>
<div v-for="column in columns" :key="column.id">
<div
class="card-container"
:style="{ height: column.height + '%' }"
:class="{ active: column.id === currentInput }"
>
<div class="card-inner">
<input
type="radio"
name="cardRadioGroup"
:value="column.id"
v-model="currentInput"
/>
<template v-if="column.gbAmount === null"> Onbeperkt </template>
<template v-else> {{ column.gbAmount }} GB </template>
{{ currentInput }}
</div>
</div>
</div>
</template>
<script lang="ts">
import { ref } from 'vue'
const columns = [
{
id: 1,
gbAmount: 0,
price: 5,
selectedDefault: false,
informationGet: ['bla', 'bla'],
informationUsing: 'Boop.',
recommended: false,
height: 16.66,
},
{
id: 2,
gbAmount: 1,
price: 10,
selectedDefault: false,
informationGet: ['beh', 'beh'],
informationUsing: 'Beep',
recommended: false,
height: 33.33,
},
]
export default {
name: 'Card',
setup() {
const currentInput = ref(columns[0].id)
return {
columns,
currentInput,
}
},
}
</script>
I am trying to display images in a Vuetify data table column, but the image is not displaying in the desired slot, and only shows the URL of the image, e.g. "9384053.jpg". How do I display an image using slots in Vuetify?
Segment is an array containing image URLs such as 93034.jpg, 9348903.jpg etc. I am trying to display the first image only e.g. Segment[0] with a sample output of 846454.jpg.
<v-card>
<v-card-title>
Animals
<v-spacer></v-spacer>
</v-card-title>
<v-data-table
:headers="headers"
:items="entries"
:items-per-page="12"
class="elevation-3"
:multi-sort="true"
mobile-breakpoint
:search="search"
>
<template v-slot:item.Image="{ item }">
<img :src="require(`${item.Image}`)" style="width: 50px; height: 50px" />
</template>
</v-data-table>
</v-card>
Here is the script file
<script>
import firebase from '../firebaseConfig';
const db = firebase.database().ref('/');
export default {
name: 'Animals',
data: () => ({
search: '',
entries: [],
headers: [
{ text: 'ID', value: 'ID' },
{ text: 'RFID', value: 'RFID' },
{ text: 'Image', value: 'Segment[0]' },
{ text: 'Age', value: 'Age Years' },
{ text: 'Weight', value: 'Weight' },
],
}),
methods: {
readAnimals() {
db.once('value', (snapshot) => {
snapshot.forEach((doc) => {
const dataRetrieve = doc.val();
this.$data.entries.push({
ID: dataRetrieve.ID,
RFID: dataRetrieve.RFID,
'Age Years': dataRetrieve['Age Years']
Weight: dataRetrieve.Weight,
Length_History: dataRetrieve['Length_History'],
Length: dataRetrieve.Length,
Tag: dataRetrieve.Tag,
Head: dataRetrieve.Head,
Segment: dataRetrieve.Segment,
});
});
return this.$data.entries;
}).catch((error) => {
console.log('error getting documents', error);
});
},
},
mounted() {
this.readAnimals();
},
};
</script>
<template v-slot:item.Image="{ item }">
<img :src="item.Image" style="width: 50px; height: 50px" />
</template>
You should bind it this way I think.
This seems to do the trick
<template v-slot:item.Segment[0]="{item}">
<img :src="item.Segment[0]" style="width: 50px; height: 50px" />
</template>
https://imgur.com/a/LX7JKoy
Why my b-table displays all columns of my table even I only selected some?
Here is my server-side code that calls the selected columns. Also, it worked if I use bootstrap only not bootstrap-vue.
router.get('/users', function(req, res) {
/* Get the person who has the latest date */
let getUser = "SELECT DISTINCT(MEMB.MEMB_N), MAX(PrintDate) AS PrintDate, MEMB.* \
FROM MEMB LEFT JOIN VD_Print ON MEMB.MEMB_N = VD_Print.MEMB_N GROUP BY MEMB.LAST_M \
ORDER BY PrintDate DESC LIMIT 100;"
myDB.query(getUser, function(err, rows) {
if (err) {
console.log(err);
} else {
console.log(rows);
res.send(rows);
}
});
});
And this one is on my client-side which is vuejs
<template>
<section>
<div class="sidebar"></div>
<div>
<b-form-input class="searchBar" placeholder="Search Here"></b-form-input>
</div>
<div>
<b-table class="table" striped hover :items="results"></b-table>
</div>
<b-button class="printBtn">PRINT</b-button>
</section>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
results: [],
};
},
mounted() {
this.getUsers();
},
methods: {
getUsers: function() {
axios
.get("http://localhost:9000/api/users/")
.then(response => (this.results = response.data))
.catch(error => alert(error));
}
}
};
</script>
My JSON looks like this:
You need to define the your column name in field definition of b-table. If you multiple filed in response but you want to display some fields.
Please below code and working demo.
CODE SNIPPET
export default {
data() {
return {
selectAll: false,
records: [],
perPage: 10,
currentPage: 1,
pageOptions: [5, 10, 15],
column: [{
key: "name",
sortable: true,
label: "Log File Name"
}, {
key: "lastModified",
sortable: true,
label: "Last Modified Date",
class: "text-right options-column"
}]
};
}
}
<template>
<div>
<div v-if="!hasRecords" style="text-align: center"><br><br>LOADING DATA...</div>
<div style="padding: 15px;" v-if="hasRecords">
<b-table :items="records" :fields="column" striped hover :current-page="currentPage" :per-page="perPage">
</b-table>
<b-row>
<b-col md="6" class="my-1">
<b-pagination :total-rows="totalRows" :per-page="perPage" v-model="currentPage" class="my-0" />
</b-col>
<b-col md="6" class="my-1">
<b-form-group horizontal label="Per page" class="mb-0">
<b-form-select :options="pageOptions" v-model="perPage" />
</b-form-group>
</b-col>
</b-row>
</div>
</div>
</template>