Checkbox in a table using Quasar - vue.js

Im trying to insert a checkbox column using quasar. The way I did, it only appears as the first element of the table, and I want it as the second element. How do I do this?
Example:
export default {
name: 'DespesasGeraisBKOOnline',
data() {
return{
columns: [
{
name: 'acoes',
label: 'Ações',
field: (row) => row.acoes,
sortable: true,
align: 'center',
},
{
name: 'pc',
align: 'center',
label: 'PC ',
sortable: false,
},
{
name: 'criada_em',
label: 'Criada em',
field: (row) => row.criada_em,
sortable: true,
align: 'center',
},
{
name: 'nome',
label: 'Nome',
field: (row) => row.nome,
sortable: true,
align: 'center',
},
}
}
<q-table
:data="data"
:columns="columns"
row-key="id"
selection="multiple"
class="default-table q-mt-xs"
>
<template v-slot:no-data="{}">
<div class="full-width row flex-center no-data-finded q-gutter-sm">
<span>
{{ loading ? 'Carregando...' : 'Nenhuma despesa encontrada.' }}
</span>
</div>
</template>
</q-table>
If you run the code, you can see that the first column is the "checkbox". However, I want this as the second column.

<template v-slot:body="props">
<q-tr :props="props">
<q-td key="text" :props="props">{{ props.row.title }}</q-td>
<q-td key="radio" :props="props"><q-radio v-model="input" :label="props.row.label" /></q-td>
<q-td key="checkbox" :props="props"><q-checkbox v-model="input" :label="props.row.label" /></q-td>
<q-td key="button" :props="props"><q-btn label="btn" #click="method"/></q-td>
</q-tr>
</template>
This is the way i usually define table if i want to insert any form control peacefully within any column

Related

Vuejs 3 using i18n translation inside "script setup>

I have a Laravel + Inertiajs + Vue 3 with Vite
I user Quasar framework so in one vue file I have a Quasar table.
Now I need to translate the column labels.
<template>
<head title="Elenco utenti"></head>
<AuthenticatedLayout>
<template #header>
<div>
<q-toolbar class="q-gutter-sm">
<Link :href="route('list-utenti')" type="button" class="float-right"><q-btn flat round dense icon="people" /></Link>
<div class="text-subtitle1">{{ $t('utenti.pagetitle')}}</div>
</q-toolbar>
</div>
</template>
<div class="q-py-md q-gutter-sm">
<Link :href="route('register')" type="button" class="float-right"><q-btn icon="add_box" color="white" text-color="text-grey-7" :label="$t('utenti.btn_new')"></q-btn></Link>
</div>
<div class="q-py-xl">
<q-table
title=""
:rows="users"
:columns="columns"
row-key="id"
>
<template v-slot:body-cell-actions="props">
<q-td :props="props">
<q-btn icon="mode_edit" #click="onEdit(props.row)"></q-btn>
<q-btn icon="person_off" #click="onDelete(props.row)"></q-btn>
</q-td>
</template>
<template v-slot:body-cell-email="props">
<q-td :props="props">
<strong>{{ props.value }} </strong>
</q-td>
</template>
</q-table>
</div>
</AuthenticatedLayout>
</template>
As you can see in the template code, I configured i18n and I can correctly translate with {{ $t('utenti.pagetitle') }} when in template.
now this is the script part
<script setup>
import AuthenticatedLayout from '#/Layouts/AuthenticatedLayout.vue';
import { Inertia } from '#inertiajs/inertia';
import { Link } from '#inertiajs/inertia-vue3';
import { computed, ref} from '#vue/reactivity';
import { Quasar, useQuasar } from 'quasar';
const props = defineProps({
page_description : String,
title: String,
numero_record: Number,
users: Array
});
const columns = [
{
name: 'id',
required: true,
label: 'id',
align: 'left',
field: row => row.id,
format: val => `${val}`,
sortable: false
},
{ name: 'name', align: 'left', label: translated_name, field: 'name', sortable: true},
{ name: 'email', align: 'left', label: 'e-mail', field: 'email', sortable: false},
{ name: 'ruolo', align: 'left', label: 'ruolo', field: 'ruolo', sortable: true},
{ name: 'listino_grossista_visible', align: 'center', label: 'list. grossista', field: 'listino_grossista_visible', sortable: true},
{ name: 'enabled', align: 'center', label: 'Attivo', field: 'enabled', sortable: true},
{ name: 'actions', align: 'center', label: 'Azioni'}
]
const onEdit = (row) => {
Inertia.post(route('edit-utente'),
{ row } ,
{ onBefore: () => confirm('Vuoi veramente modificarlo?')}
)
}
const onDelete = (row) => {
alert('DELETE ' + row.email);
}
</script>
I would like to use in some way $t to get the correct translation for the grid columns labels (for example 'translated_name' but I don' understand how I can do it as it is in the script part and I can not use same as in template.
I probably understood that I need to add some computed properties but I didn't exactly figured out how. Consider I'm using composition api.
const translated_name = computed(() => {
return $t('utenti.nome')
})
I checked also this link Vue-i18n not translating inside component script tags but I didn't understood how to adapt to my case.
kind regards,
Matt

How to add dynamic button for each row in quasar table

I am trying to add buttons for table rows without using a slot. I am trying to push buttons in the column I am sharing bellow:
const columns = [
{
name: 'name',
required: true,
label: 'Member No.',
align: 'left',
field: row => row.name,
format: val => `${val}`,
sortable: true
},
{ name: 'short_name', align: 'left', label: 'Short Name', field: 'short_name',
sortable:true},
{ name: 'address', align: 'left', label: 'Address', field: 'address', sortable:true},
{ name: 'ward_count', align: 'left', label: 'Ward No', field: 'ward_count', sortable:true},
{ name: 'bed_count', align: 'left', label: 'Bed No', field: 'bed_count'},
{ name: 'entry_by', align: 'left', label: 'Entry By', field: 'entry_by'}
]
From Template :
<q-table
title="Treats"
:rows="rows"
:columns="columns"
row-key="id"
v-model:pagination="pagination"
:loading="loading"
:filter="filter"
#request="onRequest"
binary-state-sort
>
<template v-slot:top-right>
<q-input borderless dense debounce="300" v-model="filter"
placeholder="Search">
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</template>
</q-table>
These buttons should pass current row id as well.
Here is some sample code from my project, this is how i do it.. let me know if you need more details..
<q-table row-key="id" title :rows="arrData" :columns="arrColumns"
v-model:pagination="pagination" :filter="filter" #request="request" binary-state-sort separator="cell" class="tableStyle outline">
<template v-slot:body-cell-your_button_column_name="props">
<q-td :props="props">
<q-btn round unelevated color="red" #click="onButtonClick(props.row.id)" label="Your Button Label"></q-btn>
</q-td>
</template>
</q-table>

Quasar: How to give props in q-table to parent component?

I have created TableTop5 component using q-table, so that I can reuse it in VisitorSummary.vue, but I have no clue how to get props which should be written in v-slot:header and v-slot:body.
VisitorSummary.vue
...
<div class="row card-wrap row-sec">
<table-top-5 title="검색어 TOP5" titleWord="검색어 TOP5"
:data="data" :columns="columns" :rowFirst="rank" // <-- it gives me errors..
:rowSec="keyword" :rowThird="visitor" :props="props" // <-- i can feel it isn't right..
>
</table-top-5>
</div>
...
<script lang="ts">
import Vue from 'vue';
import axios from 'axios';
import VueApexCharts from 'vue-apexcharts'
import NumberCount from 'components/card/NumberCount.vue'
import NumberCountSet from 'components/card/NumberCountSet.vue';
import TitleWithTooltip from 'components/card/TitleWithTooltip.vue'
import TableTop5 from 'components/table/TableTop5'
Vue.use(VueApexCharts)
Vue.component('apexchart', VueApexCharts)
export default Vue.extend({
components: {
NumberCountSet,
NumberCount,
TitleWithTooltip,
TableTop5,
},
data() {
return {
columns: [
{
name: 'rank',
required: true,
label: '순위',
align: 'center',
field: row => row.rank,
format: val => `${val}`,
sortable: true,
style: 'width: 10%;'
},
{ name: 'keyword', align: 'left', label: '검색어', field: 'keyword', sortable: true,
style: 'width: 70%; background:RGBA(0,178,45,0.05) ' },
{ name: 'visitor', align: 'center', label: '방문자수', field: 'visitor', sortable: true, style: 'width: 20%' },
],
data: [
{
rank: 1,
keyword: 'slimplanet',
visitor: 25,
},
{
rank: 2,
keyword: 'test',
visitor: 58,
},
{
rank: 3,
keyword: 'test',
visitor: 64,
},
{
rank: 4,
keyword: 'Slimplanet',
visitor: 72,
},
{
rank: 5,
keyword: 'test',
visitor: 18,
},
],
};
},
});
</script>
TableTop5.vue
<template>
<q-card class="card-item">
<q-card-section class="q-pa-none">
<div>
<q-table
:data="data"
:columns="columns"
row-key="name"
class="no-shadow q-pb-md q-px-md"
:hide-pagination="true"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th
v-for="col in props.cols"
:key="col.name"
:props="props"
style="font-weight: bold"
>
{{ col.label }}
</q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td key="rowFirst" :props="props">
{{ rowFirst }}
</q-td>
<q-td key="rowSec" :props="props">
{{ props.row.rowSec }}
</q-td>
<q-td key="rowThird" :props="props">
<q-badge color="black" outline>
{{ props.row.rowThird }}
</q-badge>
</q-td>
</q-tr>
</template>
</q-table>
</div>
</q-card-section>
</q-card>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
name: 'TableTop5',
props: {
title: {
type: String
},
titleWord: {
type: String
},
data: {
type: Array
},
columns: {
type: Array
},
rowFirst: {
type: String
},
rowSec: {
type: String
},
rowThird: {
type: String
},
props: {
type: Object
}
}
});
</script>
Or should i just not reuse and write q-table whenever I need it in a row?
This can be done in multiple ways. You can define it like this where the parent component takes care of rendering rows and columns. You can also define some columns that every table needs to have and have a slot for extra columns.
You could also iterate over the columns so you render them dynamically.
Either way, the advantage to this approach, is consistency and reusability, in case you have some complex logic inside the table for filtering and other stuff.
TableTop5
<template>
<q-table :data="data" :columns="columns">
<template #body="props">
<slot v-bind="props" name="columns"></slot>
</template>
</q-table>
</template>
<script>
export default {
name: 'TableTop5',
props: {
data: {
type: Array,
},
columns: {
type: Array,
},
},
};
</script>
VisitorSummary
<template>
<div>
...
<table-top5 :data="data" :columns="columns">
<template #columns="props">
<q-tr>
<q-td key="c1">
{{ props.row.c1 }}
</q-td>
<q-td key="c2">
{{ props.row.c2 }}
</q-td>
</q-tr>
</template>
</table-top5>
...
</div>
</template>
<script>
import TableTop5 from '#/TableTop5.vue';
export default {
name: 'VisitorSummary',
components: {
TableTop5,
},
data() {
return {
columns: [
{
name: 'c1',
label: 'Col 1',
field: 'c1',
align: 'left',
},
{
name: 'c1',
label: 'Col 2',
field: 'c2',
align: 'left',
},
],
data: [
{
c1: 'C1 data - row 1',
c2: 'C2 data - row 1',
},
{
c1: 'C1 data - row 2',
c2: 'C2 data - row 2',
},
],
};
},
};
</script>

How to combine an Expandable Table with an Expansion Panel in Vuetify?

I'd like to combine two separate Vuetify functionalities into one:
https://vuetifyjs.com/en/components/data-tables --> Expandable Rows Table (but ideally with more than one data row upon expansion)
https://vuetifyjs.com/en/components/expansion-panels --> External Control Expansion Panel
Ultimately, the goal is to have a table that looks like this (Grouping Table with expand/collapse all one): https://codepen.io/lzhoucs/pen/aadaJx
The issue with this table is that despite fitting the code into my project, certain functionalities don't work -- such as clicking to open and close a table. I believe this is due to this being a different version of Vue than what I'm using, which is the most up to date, as I spotted some old styles.
I've tried a bunch of things, but my most successful attempt is creating a table within a table. Here is the code for that:
<template>
<v-container>
<v-data-table
:headers="headers"
:items="projects"
:expanded="expanded"
item-key="name"
show-expand
class="elevation-1"
#click:row="clicked"
>
<template v-slot:expanded-item="{ headers }">
<td :colspan="headers.length">
<v-data-table
:headers="peopleHeaders"
:items="people"
item-key='name'
hide-default-footer
class='elevation-1'>
<template slot="item" slot-scope="props">
<tr>
<td>{{props.item.name}}</td>
<td>{{props.item.major}}</td>
<td>{{props.item.preference}}</td>
<td>
<v-btn color='success'>Accept</v-btn>
<v-btn color='error'>Reject</v-btn>
</td>
</tr>
</template>
</v-data-table>
</td>
</template>
</v-data-table>
</v-container>
</template>
<script>
export default {
data() {
return {
expanded: [],
headers: [
{
text: 'Name',
align: 'left',
sortable: true,
value: 'name',
},
{ text: 'Status', value: 'Status' },
],
projects: [
{
name: '#this is the project they applied to',
Status: 'Status: Pending',
},
],
peopleHeaders: [
{
text: 'Name',
align: 'left',
sortable: true,
value: 'name',
},
{
text: 'Major',
align: 'left',
sortable: true,
value: 'major',
},
{
text: 'Preference',
align: 'left',
sortable: true,
value: 'preference',
},
],
people: [
{
name: 'BORB',
major: 'SWE',
preference: 'idk',
},
],
};
},
methods: {
clicked(value) {
this.expanded.push(value);
},
},
};
</script>
Any advice for how to combine the two features to achieve the table desired would be greatly appreciated.

How to target specific vue table element?

I'm setting up a list that fetches from a database and displays a list of orders. onclick of the button, I would like to show the stars-rating div only in the row it was clicked on. How do I make a vue button trigger the appearance of a div only in the row that it is in.
I've tried using v-on:click= function to call another function in js but didn't seem to work. Here both templates are contained in
<div id="wrapper">
<v-toolbar flat color="white">
<v-toolbar-title style="font-family: 'Raleway', sans-serif;">Order
History</v-toolbar-title>
<v-spacer></v-spacer>
<d style="margin-right:20px;color:#a7a7a7;font-family: 'Raleway',
sans-serif;">click on an order for more information</d>
</v-toolbar>
<v-data-table
:headers="headers"
:items="orders"
:expand="expand"
item-key="number"
>
<template v-slot:items="props">
<tr #click="props.expanded = !props.expanded">
<!--trigger using this button--> <td class="text-xs-left" style='font-
weight:400;'><v-btn v-on:click="greet"
class="dark">{{ props.item.review }}</v-btn>
</td>
</tr>
</template>
<template v-slot:expand="props" style="font-
weight:500">
<v-data-table
:items="[props.item]"
:expand="expand"
item-key="name"
hide-actions
>
<template v-slot:headers="props">
</template>
<template v-slot:items="props">
<td width="15%" class="text-xs-left"
style='font-weight:300;'>
<!--trigger this div --> <div class="star-rating"></div>
</td>
</template>
</v-data-table>
</template>
</v-data-table>
</div>
//JS
var v = new Vue({
el: '#app',
methods: {
greet: function () {
$(".stars-rating").hide();
}
},
data() {
return {
expand: true,
headers: [
{
text: 'Order Number',
align: 'left',
sortable: false,
value: 'number',
width: '10%' },
{ text: 'Name/Message', value: 'name',
align: 'left',
width: '15%' },
{ text: 'Date/Start', value: 'date',
align: 'left',
width: '10%' },
{ text: 'Time/End', value: 'time',
align: 'left',
width: '10%' },
{ text: 'Provider/Receipts', value: 'provider',
align: 'left',
width: '10%' },
{ text: 'Amount/Labor', value: 'amount',
align: 'left',
width: '15%' },
{ text: 'Status/Tracking', value: 'status',
align: 'left',
width: '15%' },
{ text: 'Confirmation/Review', value: 'review',
align: 'left',
width: '15%' }],
orders: [],
};
} });
have you tried with
<div class="star-rating" v-if="props.expanded"></div>
First of all, you should remove the #click from your <tr #click="props.expanded = !props.expanded"> element.
In your greet function, you have to change the expand flag, something like:
greet: function () {
this.expand = false
}
As you are already biding the expand state with the v-data-table expand prop, it should work
<v-data-table
:headers="headers"
:items="orders"
:expand="expand"
item-key="number"
>