How to add tooltip to datatable header in vuetify? - javascript

In older version on vuetify you could access headerCell slot and easily add tooltips - see https://codepen.io/nueko/pen/dZoXeZ
In the latest version you have named slots, so you need to know header name before
<template v-slot:header.givenname="{ header }">
Is there a way to add a tooltip to all headers?

There are 2 ways to achieve this.
Option 1: Customizing whole table row
If you need to customize whole row element inside table heading this might be useful. Even though I would not recommend to follow this way if you don't want to loose sorting functionality which exist by default in v-data-table.
Example:
<template v-slot:header="{ props: { headers } }">
<thead>
<tr>
<th v-for="h in headers">
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<span v-on="on">{{h.text}}</span>
</template>
<span>{{h.text}}</span>
</v-tooltip>
</th>
</tr>
</thead>
</template>
Working pen: https://codepen.io/onelly/pen/QWWmpZN
Option 2: Customizing each heading without losing sorting functionality
I guess this is more like what you are trying to do and the replacement for the old way. You can loop <template v-slot:header> and use Dynamic Slot Names to accomplish this. Syntax for Dynamic slot name looks like this <template v-slot:[dynamicSlotName]>.
Example:
<template v-for="h in headers" v-slot:[`header.${h.value}`]="{ header }">
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<span v-on="on">{{h.text}}</span>
</template>
<span>{{h.text}}</span>
</v-tooltip>
</template>
Working pen: https://codepen.io/onelly/pen/ExxEmWd

Related

Vuetify use v-html inside data table cell

I've an object with values what come from server with HTML tags like span,p, and I'm using vuetify data table to display this values, the problem is what I don't know how to render this HTML in table cell I know there is v-html directive, but how to use this directive with vuetify.
I found an example that modify values from specific columns:
<v-data-table
:headers="headers"
:items="rows"
:search="search"
dense>
<template v-slot:item.name="{ item }">
<span v-html="item.name"></span>
</template>
</v-data-table>
Here name is just one column, how can I use this example for each columns?
You could do that dynamically by looping through headers values :
<v-data-table
:headers="headers"
:items="rows"
:search="search"
dense>
<template v-for="header in headers" v-slot:item[header.value]="{ item }">
<div v-html="item[header.value]"></div>
</template>
</v-data-table>
When I tried a solution with slots (see above), ESLint trows an error: "An element cannot have multiple <template> elements which are distributed to the same slot". To solve this problem, I used the v-simple-table instead of v-data-table and used v-html to render table data (see codepen). But be aware that v-html may be used only in cases when the table data are not modified by users, otherwise it's a possibility for an XSS attack.
<v-simple-table>
<template v-slot:default>
<thead>
<tr>
<th v-for="header in headers" :key="header.value" class="text-left">
{{ header.value }}
</th>
</tr>
</thead>
<tbody>
<tr
v-for="item in desserts"
:key="item.name"
>
<td v-for="header in headers" :key="header.value" v-html="item[header.value]"></td>
</tr>
</tbody>
</template>
</v-simple-table>

Vue dynamic components not re rendering inside v-for loop when data changes

I have dynamic table component where I can modify columns (ordering, adding new, removing columns). Table body looks like this:
<tr v-for="row in data" :key="row.id">
<td v-for="column in columns" :key="column.slug">
<component
v-if="column.component"
:is="column.component"
v-bind="{ row: row, countries: row.reach }"
/>
<template v-else>
{{ row[column.slug] }}
</template>
</td>
</tr>
Everything works well except when I edit data (add new column or rearrange the order) then every component inside table body disappears and is not rendered. I tried to attach unique :key to <component> but was not able to make it work. When I inspect table body in Vue devtools I can see that components are inside just not rendered into DOM. When inspecting table body in chrome devtools I can see only <!--function(e,n,r,o){return dn(t,e,n,r,o,!0)}--> in place where component should be rendered. Any ideas what I might be doing wrong here?
You are using duplicated keys. You should provide unique keys for all v-for elements inside the whole component. Try this (see key for every column):
<tr v-for="row in data" :key="row.id">
<td v-for="column in columns" :key="`${row.id}/${column.slug}`">
<component
v-if="column.component"
:is="column.component"
v-bind="{ row: row, countries: row.reach }"
/>
<template v-else>
{{ row[column.slug] }}
</template>
</td>
</tr>
Also when you are in development it is highly recommended to use Vue development mode. It will highlight errors like this.
Turns out I was passing Component object into :is directive instead of string with Component name. That's why it was not rendered properly.

What is the purpose of <template> usage in Vuetify?

I want to use Vuetify 2.0 in my project and currently reading about v-stepper component which is used to display progress through numbered steps.
In the playground example provided I see that they are using <template> element to wrap content of v-stepper component. HTML looks something like this (note: I removed unnecessary details):
<v-stepper>
<template v-for="n in steps">
<v-stepper-content
:key="`${n}-content`"
:step="n"
>
</v-stepper-content>
</template>
</v-stepper>
Notice the <template> tag used. What is the purpose of it? When should I use it as opposed to just putting the <v-stepper-content> directly inside of <v-stepper>?
I've read a bit about element on MDN but I am not sure how to use it specifically with Vuetify (or more generally with Vue.Js or just pure HTML/CSS/JS for that matter).
a <template> in the context of a v-for loop is an organizational item.
It does not get rendered by the browser. It is there to help with more complex rendering situations, where you don't want to limit yourself to a single element
In most cases you have a pretty straight forward mapping of items, each item in an array gets a <li> element. If this is the case, you're not likely to use this.
Here is an example of a problem where it might help...
Let's say you want to loop through an array of objects, and render a v-btn if the object is a button, and a v-image if the object is an image.
without template...
<span v-for="item in items">
<v-btn v-if="item.isBtn"></v-btn>
<v-img v-else-if="item.isImg"></v-img>
</span>
The problem is that each item will be wrapped in the span.
<span>
<v-btn/>
</span>
<span>
<v-img/>
</span>
<span>
<v-btn/>
</span>
If you, however, use the template element, the wrapping element is no longer there.
<template v-for="item in items">
<v-btn v-if="item.isBtn"></v-btn>
<v-img v-else-if="item.isImg"></v-img>
</template>
and you will get...
<v-btn/>
<v-img/>
<v-btn/>
You can also have it return multiple items in one instance of the loop.
in the vue docs at https://v2.vuejs.org/v2/guide/list.html#v-for-on-a-lt-template-gt
it shows an example of rendering more than one item per iteration:
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
There are some other cases where this might be helpful but not likely something you come across on a daily basis.
TL;DR;
Vue doesn't render the <template> element. It helps organize code chunk without the need of a single child element when looping
part 2.
When should I use it as opposed to just putting the directly inside of ?
Because the structure of vertical and horizontal steppers is different, the vuetify authors used it in the playground to allow users to toggle it. The first level of template (<template v-if="vertical">) is used do determine whether the next level should render the v-stepper-step elements as vertical or as horizontal. The second level is used to do the iterating of items.
example:
vertical (step and content are siblings):
<template>
<v-stepper v-model="e6" vertical>
<v-stepper-step :complete="e6 > 1" step="1">
Select an app
<small>Summarize if needed</small>
</v-stepper-step>
<v-stepper-content step="1">
<v-card color="grey lighten-1" class="mb-12" height="200px"></v-card>
<v-btn color="primary" #click="e6 = 2">Continue</v-btn>
<v-btn text>Cancel</v-btn>
</v-stepper-content>
<v-stepper-content step="2">...</v-stepper-content>
<v-stepper-step :complete="e6 > 3" step="3">...</v-stepper-step>
</v-stepper>
</template>
horizontal (each step is separate):
<template>
<div>
<v-stepper>
<v-stepper-header>
<v-stepper-step step="1">Select campaign settings</v-stepper-step>
<v-divider></v-divider>
<v-stepper-step step="2">Create an ad group</v-stepper-step>
<v-divider></v-divider>
<v-stepper-step step="3">Create an ad</v-stepper-step>
</v-stepper-header>
</v-stepper>
<v-stepper value="2" class="mt-12">
...
</v-stepper>
<v-stepper value="3" class="mt-12">
...
</v-stepper>
</div>
</template>

Polymer Iron-selector - Deselect the template on Save

I am having odd behavior with Polymer 1 Iron-selector
Below is my code.
<iron-selector selected="{{_selectedIndex}}">
<template is="dom-if" if="[[colors.length]]">
<colors-item colors="[[colors]]"></colors-item>
</template>
<template is="dom-repeat" items="{{colorways}}">
<colorway-item colorway="{{item}}"></colorway-item>
</template>
and in Properties selectedIndex looks like this
_selectedIndex: Number,
If I make changes and save, I want the selected to be none. How can i do this?

Complex headers in angular2-data-table

I'm trying to create a table with a complex header (multi-line header) like this:
using the angular-2-data-table library found here:
https://github.com/swimlane/angular2-data-table
They have something called "Expressive cell templates" in which you can define columns like this:
<datatable
class="material"
[rows]="rows"
[options]="options">
<datatable-column name="Name">
<template let-column="column">
Hi + {{column.name}}
</template>
<template let-value="value">
Hi: <strong>{{value}}</strong>
</template>
</datatable-column>
<datatable-column name="Gender">
<template let-row="row" let-value="value">
My name is: <i [innerHTML]="row['name']"></i> and <i>{{value}}</i>
<div>{{joke}}</div>
</template>
</datatable-column>
</datatable>
plnkr here
But it seems like the column name is always defined as text, and it's unclear how you would have nested column names. Any ideas if complex headers are possible in angular2-data-table? It's possible in regular datatables (https://datatables.net/examples/advanced_init/complex_header.html).
Thanks in advance!

Categories

Resources