Vue data passing component to component isn't working - vue.js

I am trying to make a common table component for my project. So, I created a paginationtable.vue component as a master table. And trying to send column and row values using props. But my page can't render row values. But column values are not affecting. Here I am adding some codes.
PaginationTable.Vue:
<template>
<q-table :data="data" :columns="columns">
<template #body="props">
<slot v-bind="props" name="data"></slot>
</template>
</q-table>
</template>
<script>
export default {
name: "PaginationTable",
props: {
data: {
type: Array,
},
columns: {
type: Array,
},
},
};
</script>
Paginationtable.vue is my master table component where I am sending my data. Now adding codes for child component:
DashboardPage.vue:
<template>
<div class="q-pa-md">
<PaginationTableVue
title="Recent Transactions"
:data="data"
:columns="columns"
>
<template #columns="props">
<q-tr>
<q-td key="dateAndTime">
{{ props.row.dateAndTime }}
</q-td>
<q-td key="from">
{{ props.row.from }}
</q-td>
<q-td key="to">
{{ props.row.to }}
</q-td>
<q-td key="transactionType">
{{ props.row.transactionType }}
</q-td>
<q-td key="channel">
{{ props.row.channel }}
</q-td>
<q-td key="transactionAmount">
{{ props.row.transactionAmount }}
</q-td>
<q-td key="trasactionId">
{{ props.row.trasactionId }}
</q-td>
<q-td key="reference">
{{ props.row.reference }}
</q-td>
<q-td key="invoiceNo">
{{ props.row.invoiceNo }}
</q-td>
<q-td key="couponAmount">
{{ props.row.couponAmount }}
</q-td>
<q-td key="discountedAmount">
{{ props.row.discountedAmount }}
</q-td>
<q-td key="cashbackAmount">
{{ props.row.cashbackAmount }}
</q-td>
<q-td key="accountBalance">
{{ props.row.accountBalance }}
</q-td>
</q-tr>
</template>
</PaginationTableVue>
</div>
</template>
<script>
import PaginationTableVue from "src/components/table/PaginationTable.vue";
export default {
name: "DashboardPage",
components: {
PaginationTableVue,
},
data() {
return {
columns: [
{
name: "dateAndTime",
required: true,
label: "Date and Time",
align: "left",
field: "dateAndTime",
sortable: true,
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
},
{
name: "from",
align: "center",
label: "From",
field: "from",
sortable: true,
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
},
{
name: "to",
label: "To",
field: "to",
sortable: true,
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
},
{
name: "transactionType",
label: "Transaction Type",
field: "transactionType",
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
},
{
name: "channel",
label: "Channel",
field: "channel",
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
},
{
name: "transactionAmount",
label: "Transaction Amount",
field: "transactionAmount",
sortable: true,
sort: (a, b) => parseInt(a, 10) - parseInt(b, 10),
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
},
{
name: "trasactionId",
label: "Trasaction Id",
field: "trasactionId",
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
},
{
name: "reference",
label: "Reference",
field: "reference",
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
},
{
name: "invoiceNo",
label: "Invoice No",
field: "invoiceNo",
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
},
{
name: "couponAmount",
label: "Coupon Amount",
field: "couponAmount",
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
sortable: true,
sort: (a, b) => parseInt(a, 10) - parseInt(b, 10),
},
{
name: "discountedAmount",
label: "Discounted Amount",
field: "discountedAmount",
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
sortable: true,
sort: (a, b) => parseInt(a, 10) - parseInt(b, 10),
},
{
name: "cashbackAmount",
label: "Cashback Amount",
field: "cashbackAmount",
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
sortable: true,
sort: (a, b) => parseInt(a, 10) - parseInt(b, 10),
},
{
name: "accountBalance",
label: "Account Balance",
field: "accountBalance",
style: "color:#464646;",
headerStyle: "color:#464646; font-weight: bold;",
sortable: true,
sort: (a, b) => parseInt(a, 10) - parseInt(b, 10),
},
],
data: [
{
dateAndTime: "09/10/19 6:15 P.M",
from: "017xxxxxxxx",
to: "017xxxxxxxx",
transactionType: "Refund",
channel: "App",
transactionAmount: 1200,
trasactionId: "XDFGJHNAG",
reference: "Reference Text",
invoiceNo: 90149124,
couponAmount: 10,
discountedAmount: 10,
cashbackAmount: 10,
accountBalance: 100000,
},
],
};
},
};
</script>
Now I am adding my outputted result where I am getting column values but not rows.

Related

Modify elements with checkbox checked created by iteration

I have an array of objects in a state, the object has an id, a title and a url, I go through this array and show a div with an input checkbox and an image that corresponds to the checkbox, when I click on a checkbox using v- model I save the id in an array, if it is checked I save it, if it is not, I remove it from the array. I want that when it is checked or the checkbox id exists in the array, modify the image, if it is not, return to its original form, this with each checkbox and its corresponding image, how can I do it?
I loop through the store array and display a div with a checkbox and the image
<div v-for="item in store.items" :key="store.id">
<input
type="checkbox"
:value="item.title"
v-model="store.checkeds"
:id="item.id"
>
<img
:src="item.url"
:alt="item.title"
width="30"
height="30"
>
</div>
store
state: () => ({
checkeds: [],
items: [
{
"id": "1",
"url": "../assets/imagen.svg",
"title": "imagen"
},
{
"id": "2",
"url": "../assets/imagen2.svg",
"title": "imagen2"
},
{
"id": "3",
"url": "../assets/imagen3.svg",
"title": "imagen3"
},
{
"id": "4",
"url": "../assets/imagen4.svg",
"title": "imagen4"
},
{
"id": "5",
"url": "../assets/imagen5.svg",
"title": "imagen5"
},
{
"id": "6",
"url": "../assets/imagen6.svg",
"title": "imagen6"
},
]
})
I write a simple sample about how to manage array-style models.
<template>
<div>
<div
v-for="(item, i) in filtersStore.items" :key="item.id"
class="col-6 col-sm-4 col-lg-3 mb-3 d-flex align-items-start mb-2"
>
<input
type="checkbox"
:id="item.id"
class="mt-2"
v-model="filtersStore.checked[i]"
#change="checkedChanged"
>
<img
:src="item.urlEdited || item.url"
:alt="item.title"
:style="item.style"
>
</div>
</div>
</template>
<script>
export default {
name: 'BaseCheckBoxTest',
data() {
return {
filtersStore: {
items: [
{
id: 1,
title: 'Check 1',
url: 'https://picsum.photos/id/0/5616/3744',
style: {
width: '100px',
height: '100px',
},
},
{
id: 2,
title: 'Check 2',
url: 'https://picsum.photos/seed/picsum/200/300',
style: {
width: '100px',
height: '100px',
},
},
{
id: 3,
title: 'Check 3',
url: 'https://picsum.photos/id/1/5616/3744',
style: {
width: '100px',
height: '100px',
},
},
{
id: 4,
title: 'Check 4',
url: 'https://picsum.photos/id/1023/3955/2094',
style: {
width: '100px',
height: '100px',
},
},
],
checked: [],
},
};
},
methods: {
checkedChanged() {
this.filtersStore.checked.forEach((isChecked, index) => {
if (isChecked) {
// Apply your action here
this.filtersStore.items[index].urlEdited = this.filtersStore.items[index].url + '?grayscale';
this.filtersStore.items[index].style = {
width: '150px',
height: '150px',
};
} else {
// Remove your action here
this.filtersStore.items[index].urlEdited = undefined;
this.filtersStore.items[index].style = {
width: '100px',
height: '100px',
};
}
});
},
},
};
</script>
I store the status of checkboxes in an array (v-model="filtersStore.checked[i]"). This array provides us with the selected items. Just loop over the status array and apply your filter or action.
If you provide more information about the state and actions, I can improve it in a more practical way.
UPDATE: if a checkbox gets checked, the image style will change.

Show remaining API data on b-table through pagination

I'm trying to hit all the data from API using axios in Nuxt, but it seems only shows 10 data each page, so if there's actually 15 data which I expect to hit, it has to show 2 page (page 1 with 10 data, page 2 with the remaining 5 data). I had no idea why does it only want to show every 10 data
per page.
How to show the remaining data in next page? Here's what I've been doing so far
<script>
// eslint-disable-next-line no-unused-vars
import { getAllProvinces } from '~/api/delivery'
export default {
data() {
return {
filter: null,
filterOn: [],
perPage: 10,
currentPage: 1,
rows: 0,
items: [],
fields: [
{
key: 'id',
sortable: true,
label: 'ID',
class: 'truncate',
},
{
key: 'uploadReference',
sortable: true,
label: 'Upload Reference',
class: 'truncate',
},
{
key: 'requestId',
sortable: true,
label: 'Request ID',
class: 'truncate',
},
{
key: 'storeCode',
sortable: true,
label: 'Store Code',
class: 'truncate',
},
{
key: 'branchCode',
sortable: true,
label: 'Branch Code',
class: 'truncate',
},
{
key: 'b2bId',
sortable: true,
label: 'B2B ID',
class: 'truncate',
},
{
key: 'request',
sortable: true,
label: 'Request',
class: 'truncate',
},
{
key: 'response',
sortable: true,
label: 'Response',
class: 'truncate',
},
{
key: 'createDate',
sortable: true,
label: 'Create Date',
class: 'truncate',
},
{
key: 'errorClassification',
sortable: true,
label: 'Error Classification',
class: 'truncate',
},
],
}
},
watch: {
currentPage: {
handler(value) {
this.getAllStock()
},
},
},
created() {
this.getAllStock()
},
methods: {
getAllStock() {
this.$axios
.get(
'axioslink' +
this.currentPage +
'&status=1'
)
.then((res) => {
// eslint-disable-next-line no-console
console.log(res.data)
this.items = res.data.stocks
this.allStock = res.data
this.rows = res.data.totalDocuments
// eslint-disable-next-line no-console
})
this.rows = this.items.length
},
onFiltered(filteredItems) {
this.rows = filteredItems.length
this.currentPage = 1
},
},
}
</script>
<div class="text-center">
<b-table
id="my-table"
:per-page="perPage"
:current-page="currentPage"
striped
small
hover
dark
responsive
show-empty
:items="items"
:fields="fields"
:filter="filter"
:filter-included-fields="filterOn"
#filtered="onFiltered"
>
<template v-slot:cell()="data">
<span v-b-tooltip.hover :title="data.value">{{
data.value
}}</span>
</template>
</b-table>
</div>
</template>
<div class="overflow-auto">
<b-card-footer class="py-4 d-flex justify-content-end">
<b-pagination
:total-rows="rows"
:per-page="perPage"
aria-controls="my-table"
#change="currentPage = $event"
></b-pagination>
</b-card-footer>
</div>
Thanks and have a great day
new Vue({
el: "#menu",
data: () => ({
filter: null,
filterOn: [],
perPage: 10,
currentPage: 1,
rows: 0,
items: [],
fields: [{
key: 'id',
sortable: true,
label: 'ID',
class: 'truncate',
},
{
key: 'uploadReference',
sortable: true,
label: 'Upload Reference',
class: 'truncate',
},
{
key: 'requestId',
sortable: true,
label: 'Request ID',
class: 'truncate',
},
{
key: 'storeCode',
sortable: true,
label: 'Store Code',
class: 'truncate',
},
{
key: 'branchCode',
sortable: true,
label: 'Branch Code',
class: 'truncate',
},
{
key: 'b2bId',
sortable: true,
label: 'B2B ID',
class: 'truncate',
},
{
key: 'request',
sortable: true,
label: 'Request',
class: 'truncate',
},
{
key: 'response',
sortable: true,
label: 'Response',
class: 'truncate',
},
{
key: 'createDate',
sortable: true,
label: 'Create Date',
class: 'truncate',
},
{
key: 'errorClassification',
sortable: true,
label: 'Error Classification',
class: 'truncate',
},
],
}),
methods: {
getAllStock() {
this.items = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }, { id: 8 }, { id: 8 }, { id: 10 }, { id: 11 }, { id: 12 }, ]
// this.allStock = res.data
this.rows = this.items.length
},
onFiltered(filteredItems) {
this.rows = filteredItems.length
this.currentPage = 1
},
},
created() {
this.getAllStock()
},
});
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.18.1/bootstrap-vue.min.css" />
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.18.1/bootstrap-vue.min.js"></script>
<div id="menu">
<b-table id="my-table" :per-page="perPage" :current-page="currentPage" striped small hover dark responsive show-empty :items="items" :fields="fields" :filter="filter" :filter-included-fields="filterOn" #filtered="onFiltered">
</b-table>
<b-pagination v-model="currentPage" :total-rows="rows" :per-page="perPage" aria-controls="my-table"></b-pagination>
</div>

How to use pagination in BootstrapVue

I have created a b-table that stores all the data from the API that has been hit from Swagger UI, but since the data has a lot of characters in string, My questions are how to make the data in each row be hovered on click to show the real data from API that hasn't been truncated? I've tried using v-b-tooltip but it seems doesn't work. If I may, I also wanted to know more about how to make the b-pagination works to load another data as I navigate page further.
Here's my current code:
<template>
<base-header>
<template>
<b-card body>
<b-card-header class="border-0">
<h3 class="mb-0">Stock List</h3>
</b-card-header>
<template>
<div class="text-center">
<b-table responsive dark striped hover:true :items="items" :fields="fields">
<template #cell()="data">
<span v-b-tooltip.hover :title="data.value">
{{ data.value }}
</span>
</template>
</b-table>
</div>
</template>
<div class="overflow-auto">
<b-card-footer class="py-4 d-flex justify-content-end">
<b-pagination
v-model="currentPage"
:total-rows="rows"
:per-page="perPage"
aria-controls="my-table"
></b-pagination>
</b-card-footer>
</div>
</b-card>
</template>
</base-header>
</template>
and then here's the script
<script>
// eslint-disable-next-line no-unused-vars
import { getAllProvinces } from '~/api/delivery'
export default {
// components: {
// },
data() {
return {
perPage: 10,
currentPage: 1,
allStock: 0,
text: '',
rows: 100,
// ubah rows dan perPage biar paginationnya ada value
items: [],
fields: [
{
key: 'id',
sortable: true,
label: 'ID',
class: 'truncate',
},
{
key: 'requestId',
sortable: true,
label: 'Request ID',
class: 'truncate',
},
{
key: 'storeCode',
sortable: true,
label: 'Store Code',
class: 'truncate',
},
{
key: 'branchCode',
sortable: true,
label: 'Branch Code',
class: 'truncate',
},
{
key: 'b2bId',
sortable: true,
label: 'B2B ID',
class: 'truncate',
},
{
key: 'request',
sortable: true,
label: 'Request',
class: 'truncate',
},
{
key: 'response',
sortable: true,
label: 'Response',
class: 'truncate',
},
{
key: 'createDate',
sortable: true,
label: 'Create Date',
class: 'truncate',
},
{
key: 'errorClassification',
sortable: true,
label: 'Error Classification',
class: 'truncate',
},
],
}
},
mounted() {
this.getAllStock()
},
methods: {
getAllStock() {
this.$axios
.get(
'API Link'
)
.then((res) => {
// eslint-disable-next-line no-console
console.log(res.data)
this.items = res.data.stocks
this.allStock = res.data
// eslint-disable-next-line no-console
// console.log('cek res stock:', JSON.stringify(res.data))
})
},
computed: {
rows() {
return this.items.length
},
},
},
}
</script>
<style>
.truncate {
max-width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
The documentation is pretty self-explanatory: https://bootstrap-vue.org/docs/components/pagination
But I added several comments on the code below (the template is therefore invalid!)
<template>
<div class="overflow-auto">
<b-pagination
v-model="currentPage" // this is the most important, bind the currentPage state to the pagination component, two-way data binding
:total-rows="rows" // display how much total data there is
:per-page="perPage" // this one will tell how much data per page you want to display
aria-controls="my-table" // this is for a11y
></b-pagination>
<p class="mt-3">Current Page: {{ currentPage }}</p>
<b-table
id="my-table"
:items="items" // where to look for the data
:per-page="perPage"
:current-page="currentPage" // re-use the current value of the pagination component
small
></b-table>
</div>
</template>
<script>
export default {
data() {
return {
perPage: 3,
currentPage: 1,
items: [ // your items, that you may replace with a new array if fetching an API in between each pagination page change
{ id: 1, first_name: 'Fred', last_name: 'Flintstone' },
{ id: 2, first_name: 'Wilma', last_name: 'Flintstone' },
{ id: 3, first_name: 'Barney', last_name: 'Rubble' },
{ id: 4, first_name: 'Betty', last_name: 'Rubble' },
{ id: 5, first_name: 'Pebbles', last_name: 'Flintstone' },
{ id: 6, first_name: 'Bamm Bamm', last_name: 'Rubble' },
{ id: 7, first_name: 'The Great', last_name: 'Gazzoo' },
{ id: 8, first_name: 'Rockhead', last_name: 'Slate' },
{ id: 9, first_name: 'Pearl', last_name: 'Slaghoople' }
]
}
},
computed: {
rows() {
return this.items.length
}
}
}
</script>
Of course, depending of the amount of data, you may want to watch for the currentPage value and make a new API call, fetching the next elements.
This totally depends on the API implementation but it's essentially passing 2 rather than 1 in URL's query params or somewhere into the headers.
As you can see in Github's API here: https://docs.github.com/en/rest/reference/repos#list-repositories-for-the-authenticated-user--parameters
Theirs is awaiting for a page and per_page params, hence the values of our VueJS state that we will send a new API call with.

How to make expansion on dynamic column datatable

I have a problem, I need to make an expansion row so I did something like:
<q-table
:title="title"
:data="driverTable.data"
:columns="driverTable.columns"
:visible-columns="driverTable.visibleCols"
row-key="objectId"
:loading="driverTable.loading"
:filter="driverTable.filter"
>
<template
v-slot:body-cell-expandingrow="cellProperties"
>
<q-td
auto-width
:props="cellProperties"
>
<q-btn
size="sm"
color="accent"
round
dense
#click="cellProperties.expand = !cellProperties.expand"
:icon="cellProperties.expand ? 'remove' : 'add'"
/>
</q-td>
<q-tr
v-show="cellProperties.expand"
:props="cellProperties"
>
<q-td
colspan="100%"
>
<div
class="text-left"
>
This is expand slot for row above: {{ cellProperties.row.name }}.
</div>
</q-td>
</q-tr>
</template>
...
data() {
return {
driverTable: {
filter: '',
loading: false,
columns: [
{
name: 'objectId',
field: row => row.objectId,
format: val => '',
},
{
name: 'name',
label: 'Nom complete',
align: 'left',
field: row => row.name,
format: val => `${val}`,
sortable: true,
classes: 'ellipsis',
},
{
name: 'phone',
required: true,
label: 'Téléphone',
field: row => row.phone,
format: val => `${val}`,
},
{
name: 'position',
required: true,
label: 'Position Actuelle',
field: row => `${row.latitude}, ${row.longitude}`,
format: val => `${val}`,
},
{
name: 'carName',
required: true,
label: 'Voiture',
field: row => row.carName,
format: val => `${val}`,
sortable: true,
},
{
name: 'carSerie',
required: true,
label: 'Série',
field: row => row.carSerie,
format: val => `${val}`,
},
{
name: 'carRef',
required: true,
label: 'Référence',
field: row => row.carRef,
format: val => `${val}`,
},
{
name: 'carImage',
required: true,
label: 'Image',
field: row => row.carImage,
align: 'center',
format: val => `${val}`,
}
],
data: []
Just like quasar documentation but it display the expanding row just like another td on the table.
I know that the problem is when I make the td of btn with the row but as U see I dont use on my html any element jsut q-table to display the data table.
here is the result:

Highcharts-vue options as variable

I want to replicate the same chart several times, using different data just like here https://jsfiddle.net/BlackLabel/qndeho5u/.
The concept works quite well but when transporting it to Vue there's something going wrong as the parameters aren't copied. For example polar isn't taken by the chart.
To avoid writing the chart options all the time I save it as a variable. On the jsfiddle it works but on my Vue code it doesn't.
What am I missing here?
<template>
<v-container fluid text-xs-center style="height: 90vh; max-height: 100%;">
<v-layout row wrap>
<v-flex xs6>
<v-card flat>
<Chart :options="chart1"/>
</v-card>
</v-flex>
<v-flex xs6>
<v-card flat>
<Chart :options="chart2"/>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import Chart from '../components/Chart.vue'
import Highcharts from 'highcharts'
var testdata2 = {name:'a', value: [
// each slice of the pie gets its own color
{ y: 10, color: '#1DACE8', name: 'a' },
{ y: 30, color: '#1C366B', name: 'b' },
{ y: 45, color: '#F24D29', name: 'c' },
{ y: 93, color: '#E5C4A1', name: 'd' },
{ y: 15, color: '#C4CFD0', name: 'e' }
]}
var testdata3 = {name:'b', value:[
// each slice of the pie gets its own color
{ y: 30, color: '#1DACE8', name: '1a' },
{ y: 20, color: '#1C366B', name: '2b' },
{ y: 35, color: '#F24D29', name: '3c' },
{ y: 23, color: '#E5C4A1', name: '4d' },
{ y: 95, color: '#C4CFD0', name: '5e' }
]}
var options = {
chart: {
polar: true,
backgroundColor: '#F5F5F5'
},
credits: {
enabled: false
},
exporting: {
buttons: {
contextButton: {
theme: {
fill: "#F5F5F5"
}
}
}
},
title: {
text: 'City 1'
},
subtitle: {
text: 'Railacc stuff'
},
pane: {
startAngle: -22.5
},
xAxis: {
tickInterval: 45,
min: 0,
max: 360,
labels: false
},
plotOptions: {
series: {
pointStart: 0,
pointInterval: 45
},
column: {
pointPadding: 0,
groupPadding: 0,
colorByPoint: true
}
},
tooltip: {
formatter: function() {
return this.y, this.point.name;
}
}
}
export default {
name: 'chartapp2',
components: {
Chart,
},
data() {
return {
chart1:{
options,
legend: {
enabled: false
},
series: [{
type: 'column',
data: testdata2.value,
pointPlacement: 'between'
}]
},
chart2:{
options,
legend: {
enabled: false
},
series: [{
type: 'column',
data: testdata3.value,
pointPlacement: 'between'
}]
},
}
},
}
</script>
I have reproduced this chart for you in Vue framework. Take a look at it and let me know if something is not clear for you.
Demo:
https://codesandbox.io/s/vue-template-9xb0c?fontsize=14