How to define the width of expandable panels in Vuetify - vuetify.js

As you can see in the picture my expandable panels do not use the maximum available width.
I want the expandable panels to use the maximum width available in the data table and make the columns fit exactly the width of the header columns. In addition to that it would be great to hide the expand Button (and also make the panel not clickable) if there is not enough data to display. I know that there is a hide-actions prop for that but I do not know how to use that.
My code:
<template>
<div class="table table--fixed-layout d-flex flex-grow-1 overflow-hidden fill-height">
<div v-if="loading" class="d-flex ma-auto">
<v-progress-circular indeterminate color="primary" :width="3" />
</div>
<v-data-table
v-else
item-key="id"
hide-default-footer
fixed-header
disable-sort
:headers="headers"
:items="filteredItems"
:items-per-page="-1"
>
<template #[`header.ticketNumber`]="{ header }">
<data-table-filter :name="header.text" #change="ticketNumberFilter = $event" />
</template>
<template #[`header.title`]="{ header }">
<data-table-filter :name="header.text" #change="titleFilter = $event" />
</template>
<template #[`header.status`]="{ header }">
<data-table-filter
:name="header.text"
:default-values="filterableTicketServiceStatuses"
#change="statusFilter = $event"
>
<template #default="{ value }">{{ getTicketServiceStatusLabel(value) }}</template>
</data-table-filter>
</template>
<template #[`header.hostNames`]="{ header }">
<data-table-filter :name="header.text" #change="hostNameFilter = $event" />
</template>
<template #[`header.creator`]="{ header }">
<data-table-filter :name="header.text" #change="creatorFilter = $event" />
</template>
<template v-slot:body="{ items }">
<v-container fluid>
<tbody v-for="item in items" :key="item.id">
<v-expansion-panels>
<v-expansion-panel>
<v-expansion-panel-header>
<template v-slot:default="{ open }">
<v-col>
<ticket-number :ticket-number="item.ticketNumber" />
</v-col>
<v-col>
<td class="pl-4">{{ item.title }}</td>
</v-col>
<v-col>
<li v-for="hostName in getFirstFourTicketHostNames(item)" :key="hostName">
<div class="pt-md-2">{{ hostName }}</div>
</li>
<div v-if="item.hosts.length > 4">
<v-fade-transition leave-absolute>
<span v-if="open">
<li v-for="hostName in getRestOfTicketHostNames(item)" :key="hostName">
<div class="pt-md-2">{{ hostName }}</div>
</li>
</span>
</v-fade-transition>
</div>
</v-col>
<v-col>
{{ getTicketServiceStatusLabel(item.status) }}
</v-col>
<v-col>
{{ item.creator }}
</v-col>
<td class="table__date">{{ formatDateTime(item.creationDate) }}</td>
<v-col></v-col>
<v-col>
<td class="table__date">{{ formatDateTime(item.finishedDate) }}</td>
</v-col>
<v-col>
<td class="pl-4">
<v-icon v-if="item.notifyCustomer">{{ icons.mdiCheck }}</v-icon>
</td>
</v-col>
</template>
</v-expansion-panel-header>
</v-expansion-panel>
</v-expansion-panels>
</tbody>
</v-container>
</template>
</v-data-table>
</div>
</template>
How can I achieve that?

Related

How can I apply certain color in every component in Vuetify?

Can I apply a certain color to the whole components within the projects? I mean, not attaching class individually on every tags like:
<v-icon left>mdi-phone-in-talk</v-icon>
<div class="pink darken-2 grey--text">tel</div>
</v-row>
<v-row align="center" class="mx-0 my-2">
<v-icon left>mdi-location-enter</v-icon>
<div class="pink darken-2 grey--text">loc</div>
</v-row>
<v-row align="center" class="mx-0 my-2">
<v-icon left>mdi-discord</v-icon>
<div class="pink darken-2 grey--text">name</div>
</v-row>
<v-row align="center" class="mx-0 my-2">
<v-icon left>mdi-email</v-icon>
<div class="pink darken-2 grey--text">mail</div>
</v-row>
// every div tag has "pink darken-2", seems quite WET
I want to achieve this goal by either to apply a certain color on the specific scope of components or to do it on the whole template within the project, such like a theme. Any good suggestion?
I know I could use "theme configuration", but I'm not sure whether I can apply the customed color tone (like a background color of button) or not.
** Best: applying a certain color to the whole components within the project with no additional code on each classes **
I would simply create a new component, that can be used anywhere.
#/components/PinkGreyText.vue
<template>
<div class="pink darken-2 grey--text">
<slot />
</div>
</template>
Now register the component: https://v2.vuejs.org/v2/guide/components-registration.html
Now you should be able to use it anywhere, below is your original snippet rewritten using the custom component above.
<v-row align="center" class="mx-0 my-2">
<v-icon left>mdi-phone-in-talk</v-icon>
<pink-grey-text>tel</pink-grey-text>
</v-row>
<v-row align="center" class="mx-0 my-2">
<v-icon left>mdi-location-enter</v-icon>
<pink-grey-text>loc</pink-grey-text>
</v-row>
<v-row align="center" class="mx-0 my-2">
<v-icon left>mdi-discord</v-icon>
<pink-grey-text>name</pink-grey-text>
</v-row>
<v-row align="center" class="mx-0 my-2">
<v-icon left>mdi-email</v-icon>
<pink-grey-text>mail</pink-grey-text>
</v-row>

Vuetify Data Table Header Customization - "hide-default-header" removes sort functionality

When adding "hide-default-header" to the v-data-table, I've noticed the sort function for all columns are removed. I'd like to keep that functionality, is there a simple way to re-include sort?
It's tricky because I'm also attempting to add an additional icon with search features next to it, hence the need for a custom th template in the header.
In the code below, the 1st column is attempting to use the sort function to no avail. Any help would be appreciated in getting it working.
<v-data-table
#click:row="rowClick"
:headers="headers"
:items="arrangedList"
:search="search"
:items-per-page="10"
class="outlined elevation-0"
hide-default-header
>
<template>
<thead>
<tr>
<th :class="[
'column sortable',
pagination.descending ? 'desc' : 'asc',
headers[0].value === pagination.sortBy
? 'active'
: '',
]">
<!-- Foo1 -->
{{ headers[0].text }}
<template>
<v-btn :ripple="false" x-small icon>
<v-icon #click="changeSort(headers[0].value)" color="grey darken-1">fa-arrow-up</v-icon>
</v-btn>
</template>
<v-menu attach="#menuAnchor" :close-on-content-click="false" :nudge-height="200" offset-y content-class="gridfilter-dd" style="display: inline-block">
<template v-slot:activator="{ on }" id="menuAnchor">
<v-btn :ripple="false" x-small icon v-on="on">
<v-icon color="grey darken-1">mdi-filter-outline</v-icon>
</v-btn>
</template>
<v-card class="gridfilter-card">
<v-list-item class="gridfilter-list-item">
<v-list-item-content class="gridfilter-list-item-content">
<v-text-field v-model="filterCandyValue" label="Enter Candy #" :clearable="true"></v-text-field>
</v-list-item-content>
</v-list-item>
<v-card-actions class="gridfilter-card__actions">
<v-spacer></v-spacer>
<button type="button" class="btn btn-primary" #click="onCandyFilterApply()">
<i class="fa fa-floppy-o"></i>
Apply
</button>
</v-card-actions>
</v-card>
</v-menu>
</th>
<!-- Foo2 -->
<th>
<v-menu :close-on-content-click="false" :nudge-height="200" offset-y content-class="gridfilter-dd" style="display: inline-block">
<template v-slot:activator="{ on }" id="menuAnchor1">
<span v-on="on">{{ headers[1].text }}</span>
<v-btn :ripple="false" x-small icon v-on="on">
<v-icon color="grey darken-1">mdi-filter-outline</v-icon>
</v-btn>
</template>
<v-card class="gridfilter-card">
<v-list-item class="gridfilter-list-item">
<v-list-item-content class="gridfilter-list-item-content">
<v-text-field label="Enter Foo2 #" :clearable="true"></v-text-field>
</v-list-item-content>
</v-list-item>
<v-card-actions class="gridfilter-card__actions">
<v-spacer></v-spacer>
<button type="button" class="btn btn-primary" #click="onFilterApply()">
<i class="fa fa-floppy-o"></i>
Apply
</button>
</v-card-actions>
</v-card>
</v-menu>
</th>
</tr>
<template slot="items" slot-scope="props">
<tr :active="props.selected" #click="props.selected = !props.selected">
<td class="text-xs-right">{{ props.item.Foo1 }}</td>
<td class="text-xs-right">{{ props.item.Foo2 }}</td>
</tr>
</template>
</thead>
</template>
</v-data-table>
P.S. I was using this page as a starting point in getting the table set up: https://codepen.io/mikecole/pen/zLNKbG
Looks like you want to remove the header row, however you still want keep the sort.
So without adding hide-default-header option and keeping the header text value as empty string, you can keep the sort functionality.
HTML
<v-data-table
#click:row="rowClick"
:headers="headers"
:items="arrangedList"
:search="search"
:items-per-page="10"
class="outlined elevation-0"
>
JS
headers: [
{
text: '',align: 'left', value: 'name'
},
{ text: '', value: 'calories' },
.
.
],

How to set <v-data-table> columns to fit its content width?

How to set v-data-table columns to fit its content width ?
<v-data-table
style="background: transparent"
dense
:headers="headers"
:items="items"
disable-pagination
hide-default-footer
no-data-text="No data available"
>
<!-- Titles -->
<template
v-slot:item.title="{ item }"
>
<div class="text-primary">
{{ item.title }}
</div>
</template>
</v-data-table>

previous v-expansion-panel not closing when another one is opened

From what I've seen it should close without adding anything special but every time I click on another expandable item the previous one doesn't close.
<template>
<div d-flex p-0 m-0>
<div mb-3>
<div v-for="item in items" :key="item.Id">
<div v-if="item.HasChildren === true">
<div
class="scanList pa-2 font-weight-light"
v-ripple="{ class: 'success--text' }"
#click="swapComponent(item)"
>
{{ item.Name }}
</div>
</div>
<div v-else-if="item.HasChildren === false">
<v-expansion-panel>
<v-expansion-panel-content>
<template v-slot:header>
<div>{{ item.Name }}</div>
</template>
<v-card>
<QR justify-center :value="item.Id"></QR>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
</div>
</div>
<div v-if="model != null && model.HasChildren === false">
<v-card>
<template v-slot:header>
<div>{{ item.FullPathName }}</div>
</template>
<QR justify-center :value="model.Id"></QR>
</v-card>
</div>
</div>
<div v-if="items !== initialItems">
<div class="backButton" #click="swapPrevious()">
<v-icon class="arrow">fa-arrow-left</v-icon>
</div>
</div>
</div>
</template>
I'm on Vuetify 1.5. Thanks for the help.
You are trying to create a separate expansion panel in the loop and its independent, explicitly we can define a logic to close the other panels
Working codepen here (using vuetify 1.5x)
Changes for HTML:
Added a event trigger on wrapper around expansion panel.
Added v-model for each expansion panel.
<div v-else-if="item.HasChildren === false" #click="closeOtherPanel(item.Id)">
<v-expansion-panel v-model="panel[item.Id]">
<v-expansion-panel-content>
<template v-slot:header>
<div>{{ item.Name }}</div>
</template>
<v-card>
<QR justify-center :value="item.Id"></QR>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
</div>
Changes for script:
Add panel property inside data object.
Add a method to close other panels
data: {
panel: {},
},
methods: {
closeOtherPanel(id) {
var self = this;
Object.keys(this.panel).map(x => {
if (x != id) self.panel[x] = null;
});
}
}

Vuetify block UI for a few seconds

Loading v-for on follow code:
<v-flex class="v-card-cards" xs6 sm4 md4 lg2>
<v-card>
<v-card-title>
<span class="headline black--text">
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon color="warning" flat small v-on="on">
<v-icon>edit</v-icon>
</v-btn>
</template>
<span>{{ $t('messages.app.edit') }}</span>
</v-tooltip>
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon color="error" flat small v-on="on">
<v-icon>delete</v-icon>
</v-btn>
</template>
<span>{{ $t('messages.app.delete') }}</span>
</v-tooltip>
</span>
<v-spacer></v-spacer>
<v-icon class="profile_icon elevation-5 success--text" x-large>account_circle</v-icon>
</v-card-title>
<v-divider class="ml-0"></v-divider>
<v-list>
<v-list-tile>
<v-list-tile-action>
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-icon color="info" small v-on="on">info</v-icon>
</template>
<span>{{ $t('messages.forms.newCard.fields.firstname.label') }}</span>
</v-tooltip>
</v-list-tile-action>
<div>
<span class="caption truncate">{{ item.firstname }}</span>
</div>
</v-list-tile>
<v-divider inset></v-divider>
<v-list-tile>
<v-list-tile-action>
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-icon color="info" small v-on="on">info</v-icon>
</template>
<span>{{ $t('messages.forms.newCard.fields.lastname.label') }}</span>
</v-tooltip>
</v-list-tile-action>
<div>
<span class="caption truncate">{{ item.lastname }}</span>
</div>
</v-list-tile>
<v-divider inset></v-divider>
<v-list-tile>
<v-list-tile-action>
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-icon color="info" small v-on="on">people</v-icon>
</template>
<span>{{ $t('messages.forms.newCard.fields.groups.label') }}</span>
</v-tooltip>
</v-list-tile-action>
<div>
<span
v-for="group in item.groups"
:key="item.groups._id"
class="caption truncate"
>{{ group.description }}</span>
</div>
</v-list-tile>
<v-divider inset></v-divider>
<v-list-tile>
<v-list-tile-action>
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-icon color="info" small v-on="on">note</v-icon>
</template>
<span>{{ $t('messages.forms.newCard.fields.notes.label') }}</span>
</v-tooltip>
</v-list-tile-action>
<div>
<span class="caption truncate">{{ item.notes }}</span>
</div>
</v-list-tile>
<v-divider inset></v-divider>
</v-list>
<v-card-actions class="mx-3">
<v-spacer></v-spacer>
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-badge overlap color="info">
<template v-slot:badge>12</template>
<v-icon
large
v-on="on"
color="grey darken-1"
#click="$router.push({ name: 'dashboard' })"
>description</v-icon>
</v-badge>
</template>
<span>{{ $t('messages.forms.newCard.fields.notes.label') }}</span>
</v-tooltip>
</v-card-actions>
</v-card>
page is blocked for a few seconds, during the loading of this contents. Why? Can resolve? I have tried avoid 'v-' directive of vuetify, using only html and so not get nothing block. But i want use vuetify style.
Have tried to find other similar question on web but i don't find nothing about this argument

Resources