I'm using the vuetify tree view component to render a large list of items:
https://vuetifyjs.com/en/components/treeview/
Is there a way to paginate the loading of the children? I've seen the pagination component but I could not find a way to add pagination to the tree view component, so currently I'm just able to load the first page of the items.
Current tree view implementation:
<v-treeview v-model="selection"
#input="on_update_selection"
selectionType="leaf"
selectable
selected-color="blue"
:load-children="fetch_children"
return-object
:items="items">
<template v-slot:prepend="{ item, open }">
<v-icon v-if="item.name.endsWith('/')" :data-cy="`import-select-node-${item.name}`">
mdi-folder
</v-icon>
<v-icon v-else>
mdi-file
</v-icon>
</template>
</v-treeview>
Any guidance on how to achieve this would be super helpful!
Related
I'm trying to put a <v-menu> within the header slot of a <v-data-table>.
This menu would then show filter options (v-autocomplete) for that column.
When the menu is clicked, I can't click the autocomplete to show its items, because then the menu closes.
Is this not possible in Vuetify?
I've tried passing :close-on-click="false" and :close-on-content-click="false"
For example (CodePen):
<v-data-table :items="desserts" :headers="headers">
<template #[`header.calories`]>
<v-menu top>
<template v-slot:activator="{ on, attrs }">
<v-btn icon v-bind="attrs" v-on="on"><v-icon>filter</v-icon></v-btn>
</template>
<v-autocomplete class="black" :items="headers" />
</v-menu>
</template>
</v-data-table>
You can use Event.stopPropagation(), it will prevents further propagation of the current event
Eg:
<v-autocomplete #click="clickOnAutocomplete" class="black" :items="headers" />
...
methods: {
clickOnAutocomplete(e) {
e.stopPropagation();
},
}
....
I'm building out a Nuxt app with Vuetify, and am running into a performance issue using the Vuetify Data Tables.
On page load, I am querying for all of a user's trips. The user can then select one of those trips from a sidebar. The example user I'm testing with has a lot of categories and items contained within the first Trip, and nothing in the second Trip. When I click from the second trip back to the first trip, it takes several seconds to load the items.
From what I can tell, this bottleneck is occurring because I'm rendering a new data table for each Category (which then contains multiple Items). When I looked at the Performance tab of the Vue Devtools, I noticed that even though I am disabling pagination, sorting and filtering for the data tables, all of those events are still being fired. Here's the screenshot:
As you can see, there are upwards of 64 events being fired, most of them are duplicated twice, and events that I thought I'd disabled are still being fired. Here is a simplified version of the code that I am using:
<template>
<v-data-table
v-if="category.items"
:ref="`sortableTable${index}`"
calculate-widths
class="items-table-container"
dense
disable-filtering
disable-pagination
disable-sort
:footer-props="{ disablePagination: true, disableItemsPerPage: true }"
:headers="headers"
hide-default-footer
:items="category.items"
:mobile-breakpoint="0">
<template #body="{ items }">
<draggable
v-bind="dragOptions"
class="dragArea"
group="items"
handle=".drag"
:list="items"
tag="tbody"
#change="log"
#end="drag = false"
#start="drag = true">
<tr
v-for="(item, i) in items"
:key="item.id">
<!-- Drag Handle -->
<td
:key="`${item.id}-drag-${i}-${index}`"
class="px-0 py-1">
<custom-icon
color="#4a4a4a"
custom-class="drag"
:height="20"
name="grip-horizontal-line"
:width="20" />
</td>
<!-- Type Click To Edit -->
<td
:key="`${item.id}-type-${i}-${index}`"
class="px-0 py-1">
<click-to-edit
:style="{ fontSize: '0.875rem' }"
:unique-identifier="`type${item.id}`"
:value="item.generic_type"
#handle-update-item="updateItem($event, item, 'generic_type')" />
</td>
<!-- Other Columns, shortened to simplify -->
...
</tr>
</draggable>
</template>
</v-data-table>
</template>
Currently using Vuetify v.2.4.0.
Why are all of these events still firing? And is there a more efficient way of rendering a dozen or so Data Tables without taking such a huge performance hit?
Well, I sort of fixed it.
I ended up using Vuetify's Lazy Component, so that it's not trying to render all DOM elements at once. This has sped it up I would estimate by 75%, so much better. Not great, but better. Here's how I implanted it:
<template>
<v-row
v-for="(category, index) in trip.categories"
:key="category.id">
<v-lazy
min-height="100"
:options="{ threshold: .25}"
:style="{ width: '100%' }"
transition="fade-transition"
:value="false">
<v-col
cols="12">
<v-data-table
v-if="category.items"
:ref="`sortableTable${index}`"
calculate-widths
class="items-table-container"
dense
disable-filtering
disable-pagination
disable-sort
:footer-props="{ disablePagination: true, disableItemsPerPage: true }"
:headers="headers"
hide-default-footer
:items="category.items"
:mobile-breakpoint="0">
... custom rows
</v-data-table>
</v-vol>
</v-lazy>
</v-row>
</template>
I'm still unsure of why pagination, sorting, and filtering events are being fired even when I'm disabling those via props. I have a feeling it'd speed it up even more, so if anyone knows the answer to that, I would love to hear it!
The stock app bar component aligns items hard left, and if using the v-spacer component will the push items to the hard right.
I have tried wrapping the button items with v-container inside the v-app-bar but it breaks the layout once other components are added.
Ideally, the button on the left would align with hello and likewise with the buttons on the right, they should align with the right side of the v-container of the body.
I tried wrapping v-app-bar with v-container:
This is essentially the layout I want but obviously not with the background colour pushed in, it should fill out the width like in the first image.
Is there a native way to do this or will I need to get creative?
<template>
<v-container>
<v-app-bar
color="indigo accent-4"
dense
flat
dark
>
<v-btn icon>
<v-icon>mdi-home-outline</v-icon>
</v-btn>
<v-divider inset vertical></v-divider>
<v-btn text :key="item.id" v-for="item in items" v-text="item.text"></v-btn>
<v-spacer></v-spacer>
<v-btn text v-text="'Sign In'"></v-btn>
<v-btn text v-text="'Register'"></v-btn>
</v-app-bar>
</v-container>
</template>
Similar question but no answers. Problem with placing v-app-bar content in container?
Found a workaround in the interim, not sure how clean it is:
My solution looks like so:
The colors show the nav bar width adjusted to match the body. The code looks like so:
<template>
<v-sheet color="red">
<v-container class="pa-0">
<v-app-bar
dense
flat
color="blue accent-4"
>
<v-btn icon>
<v-icon>mdi-home-outline</v-icon>
</v-btn>
<v-divider inset vertical></v-divider>
<v-btn text :key="item.id" v-for="item in quickLinks" v-text="item.text"></v-btn>
<v-spacer></v-spacer>
<v-btn text v-text="'Sign In'"></v-btn>
<v-btn text v-text="'Register'"></v-btn>
</v-app-bar>
</v-container>
</v-sheet>
</template>
In case you want the v-app-bar to be fixed to the top of the page, I solved this by wrapping a v-app-bar inside a v-container inside another v-app-bar:
<template>
<v-app-bar app fixed dense color="grey lighten-4" elevation="1">
<v-container>
<v-app-bar dense elevation="0">
<v-app-bar-title nuxt href="/">
My Title
</v-app-bar-title>
</v-app-bar>
</v-container>
</v-app-bar>
</template>
I'd like to figure out how to hide the index/result on an empty search query.
In my blade I have the code (slightly modified from the official documentation):
<ais-instant-search index-name="myIndex" :search-client="searchClient">
<ais-search-box placeholder="Search here"></ais-search-box>
<ais-state-results>
<template slot-scope="{ state: { query } }">
<ais-hits v-if="query.length > 0">
<div slot="item" slot-scope="{ item }">
<h2>#{{ item.Title}}</h2>
<p>#{{ item.Text}}</p>
</div>
</ais-hits>
</template>
</ais-state-results>
</ais-instant-search>
If I enter a search query this works fine, but on empty query this displays the following unwanted notification on my page (instead of the before unwanted index):
Use this component to have a different layout based on a certain state.
Fill in the slot, and get access to the following things on the slot-scope:
results: [
"_rawResults",
"hits",
"nbHits",
[..]
How can I hide this notification?
Ah, I just found a solution I think.
This notification text is displayed if there's no DOM element inside <ais-hits>. And in case of no query there isn't, since "v-if" removes that. So If instead of "v-if" I use "v-show" it works as I need it, since the DOM element still exists, but isn't displayed (display:hidden).
<ais-instant-search index-name="myIndex" :search-client="searchClient">
<ais-search-box placeholder="Search here"></ais-search-box>
<ais-state-results>
<template slot-scope="{ state: { query } }">
<ais-hits v-show="query.length > 0">
<div slot="item" slot-scope="{ item }">
<h2>#{{ item.Title}}</h2>
<p>#{{ item.Text}}</p>
</div>
</ais-hits>
</template>
</ais-state-results>
I know that I can get the row selected using the event "click:row" in my Datatable component, but I need to get the specific cell that I had clicked
You can use slots for that. Add it inside of your table component like given below:
<template v-slot:item.name="{ item }">
<div #click="rowClicked(item)">
<v-icon
class="mr-2"
color="#54a1e0"
large
>{{ "mdi-folder" }}
</v-icon>
{{ item.name }}
</div>
</template>
Here, you call a "rowClicked" method and you pass the clicked item when there is a click on "name" field that you also customise within the template.