how to pass text, button and icon to v-radio elements - vue.js

<VRadioGroup :multiple="multiple" v-model="radioGroup">
<VRadio
v-for="(item, index) in options"
:key="index"
:label="item.text"
:value="item.value"
>
</VRadio>
</VRadioGroup>
I got something like this.
Question 1) I want user to be able to select all of them or as many as he wants. Looks like :multiple="true" or multiple doesn't work. I can only select one. I should also be able to unselect any of them.
Question 2) beside each v-radio, I want to have its name, button and icon. I tried the following thing(All I could find was v-radio has a label slot. I tried this:
<template slot="label" slot-scope="data">
{{ data.item.text }}
<VBtn #click="removeRadioButton(item.value)" ripple
><BaseIcon name="minus-circle" /> </VBtn
>
</template>
I put this between VRadio tags. Looks like each of them has a button and icon, but it gives me error. (item of undefined). seems like data in slot-scope is undefined.

Answer 1:
It is simple. You can change the type radioGroup to an array.
It will work.
<div id="app">
<v-app id="inspire">
<v-container fluid px-0>
{{radioGroup}}
<v-radio-group
v-model="radioGroup"
multiple=true>
<v-radio
v-for="n in 3"
:key="n"
:label="`Radio ${n}`"
:value="n"
></v-radio>
</v-radio-group>
</v-container>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
radioGroup: []
}
},
})
Note: But For multiple selections, you shouldn't use radio buttons. Go for Checkbox.
Answer 2:
Issue In your code: You're looping on the radio button.
If you want some different text on before all radio buttons then you need to loop on a div which will contain the text and icons.
<div id="app">
<v-app id="inspire">
<v-container fluid px-0>
{{radioGroup}}
<v-radio-group
v-model="radioGroup"
multiple="true">
<div
v-for="n in 3"
:key="n"
>
<span class="d-inline">
{{n}}
</span>
<v-radio
class="d-inline"
:label="`Radio ${n}`"
:value="n"
></v-radio>
<span>
icon here
</span>
</div>
</v-radio-group>
</v-container>
</v-app>
</div>

Related

Vuetify - combobox badges with a removable button

I have a combobox:
<v-combobox
v-model="selectedCategories"
:items="attributeCategories"
item-text="name"
item-value="id"
label="Category"
multiple
chips
v-on:blur="changeCategory(selectedCategories)"
></v-combobox>
It's rendered like this:
I would like to add an x on each badge, so I can quickly remove it.
Is there a setting that I need to turn on?
In regular input type text, I can just add these props
clear-icon="mdi-close-circle"
clearable
The VComboBox's selection slot enables customizing the rendering of the selections. You could add a VChip with a VIcon child that re-selects the item when clicked (thus toggling its selection, and removing the chip):
<v-combobox ⋯ chips>
<template v-slot:selection="{ attrs, item, parent, selected }">
<v-chip v-bind="attrs" :input-value="selected">
<span class="pr-2">
{{ item.name }}
</span>
<v-icon small #click="parent.selectItem(item)"> $delete </v-icon>
</v-chip>
</template>
</v-combobox>
demo
You can simply achieve that by adding the <v-icon> inside <v-chip> in the <v-slot> template. I just created the working demo with the same data set you have in the screenshot mentioned above.
Demo :
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
items: ['Weather', 'Geo Location', 'Device', 'Date and Time', 'Product'],
model: ['Weather', 'Geo Location', 'Device', 'Date and Time', 'Product']
})
})
<script src="https://unpkg.com/vue#2.x/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify#2.6.5/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify#2.6.5/dist/vuetify.min.css"/>
<div id="app">
<link rel="stylesheet" href="https://unpkg.com/#mdi/font#6.x/css/materialdesignicons.min.css"/>
<v-app id="inspire">
<v-container fluid>
<v-combobox
v-model="model"
:items="items"
label="Category"
multiple
small-chips
>
<template v-slot:selection="{ item, parent }">
<v-chip
label
small
>
<span class="pr-2">
{{ item }}
</span>
<v-icon
small
#click="parent.selectItem(item)"
>
$delete
</v-icon>
</v-chip>
</template>
</v-combobox>
</v-container>
</v-app>
</div>
There is a chips props your <v-combobox...> - so depends on Vuetify version there are two props you should add:
deletable-chips for Vuetify 2 according to docs
<v-combobox
...
chips
deletable-chips
/>
closable-chips for Vuetify 3 according to docs
<v-combobox
...
chips
closable-chips
/>
Also there is clearable prop that adds clear button on the right that clear all chips via one click (works for both Vuetify versions):
<v-combobox
...
clearable
/>

Uniquely identify button click for individual v-cards in vuejs

I am using vuejs with vuetify 1.5 i am little bit stuck in my code the issue here is i have an array of objects and based on that multiple v-cards getting generated for all the values present in the array of objects.
In multiple cards i have a button expand so by default i want to show only 4 values and onclicking expand the rest of values will be shown in the cards and that expand button but the issue is all cards will have the same expand button so on clicking expand all cards are expanding and its values are shown but I want uniquely that means when i click expand only one cards value gets expanded rest of the cards will not expand.
here is my code :-
expandToggleHandler() {
this.isExpand = !this.isExpand
},
<v-card
style="display: inline-block;"
class="cardView"
:key="rowIndex"
#sort="onSort"
#click.native = "onRowClicked(row)"
>
<v-layout wrap>
<v-flex xs12 style="text-align: center; font-weight: bold;" :style="fixedColumn && clickableColumn || clickableColumn ? 'color: #ad00ff !important;' : 'color: #3399bb'">
{{row[Object.keys(row)[0]]}}
<br />
</v-flex>
</v-layout>
<v-layout wrap>
<template v-if="!isExpand">
<template v-for= "(key, idx) of cardViewColumn">
<template v-for="(col, i) of key">
<template v-if="idx <= 1">
<v-flex xs6 sm6 md6 style="text-align: center;">
<span style="font-weight: bold;">{{ col }}</span> <br /> {{row[col]}}
</v-flex>
</template>
</template>
</template>
</template>
<template v-if="isExpand">
<template v-for= "(key, idx) of cardViewColumn">
<template v-for="(col, i) of key">
<v-flex xs6 sm6 md6 style="text-align: center;">
<span style="font-weight: bold;">{{ col }}</span> <br /> {{row[col]}}
</v-flex>
</template>
</template>
</template>
<md-button #click.stop="expandToggleHandler">{{ toggleExpandAndCollapse }}</md-button>
</v-layout>
</v-card>
and here is the image :-
in image you can see i have pressed expand button for single cards but event is getting fired for other cards too.
How can i resolve it any help with example would be appreciated.
You are using the single variable isExpand for multiple v-card components. To solve your problem I suggest to convert the variable to an array and use rowIndex as the index.
Your variable declaration should look like this:
isExpand: []
Your templates would use it like this.
<template v-if="!isExpand[rowIndex]">
</template>
<template v-else>
</template>
Please note that I replaced the second v-if with a v-else so the isExpand variable isn't checked twice.
The method would become:
expandToggleHandler(rowIndex) {
this.isExpand[rowIndex] = !this.isExpand[rowIndex]
}
And you access it like this:
<md-button #click.stop="expandToggleHandler(rowIndex)">{{ isExpand[rowIndex] ? 'Collapse' : 'Expand'}}</md-button>
I didn't know what toggleExpandAndCollapse does but I guess it handles the button label.

Hide tab headers in vuetify

I'm using #nuxtjs/vuetify with nuxt.js as combo.
I'm using the component v-tabs with v-tabs-items in my page used as grouped settings.
What i want to achieve is simple but i couldn't find the solution.
if there is just one group of settings. i don't want to show the tab header.
if there are multiple groups of settings. then the tab headers may show.
so what the code is now:
<v-tabs v-model="tab"> <!-- GROUPED SETTINGS ORDERED IN TABS -->
<v-tab class="mx-4" v-for="(tab, index) in Object.keys(content_fields)" :key="index">{{ tab }}</v-tab>
</v-tabs>
<v-tabs-items v-model="tab">
<v-tab-item>
<!-- item -->
</v-tab-item>
</v-tabs-items>
i tried to do a v-if on the v-tabs. so if there is just one group the v-tabs will not show.
but then the v-tabs-items will not show at all. even if i set the tab property on the good tab.
is there any solution that will give the result that i want?
I did with v-show:
HTML:
<div id="app">
<v-app id="inspire">
<v-tabs>
<v-tab v-show="tabs.length > 1" v-for="i in tabs" :key="i.name" :href="`#tab-${i.name}`"> {{ i.text }} </v-tab>
<v-tab-item v-for="i in tabs" :key="i.name" :value="'tab-' + i.name">
<v-card flat tile>
<v-card-text>{{ i.text }}</v-card-text>
</v-card>
</v-tab-item>
</v-tabs>
</v-app>
</div>
JS:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
tabs: [
{ name: 1, text: 'One' },
//{ name: 2, text: 'Two' }
]
}
}
})
Here you can see the live demo: https://codepen.io/ljcordero/pen/wvBXqWv
Hope this help.

Vuetify card with pagination

I have a code pen https://codepen.io/handy29/pen/YzPNWpO inside this codepen I have vuetify 2.x.x. I want implement v-card using pagination, as you can see I have a headline array and subtitle array. If you click right arrow or left arrow, headline and subtitle inside v-card change (adjust index of array) but as you can see for now this is not working. I tried using v-model="page" on v-card and using v-slot:items on v-list-item-title, but still this is not working.
HTML:
<div id="app">
<v-app id="inspire">
<v-card
:items="headlines"
v-model="page"
class="mx-auto"
max-width="344"
outlined
>
<v-list-item three-line>
<v-list-item-content>
<div class="overline mb-4">OVERLINE</div>
<v-list-item-title class="headline mb-1" v-slot:items="props">{{props}}</v-list-item-title>
<v-list-item-subtitle>This is subtitle (will be replace using array subtitle)</v-list-item-subtitle>
</v-list-item-content>
<v-list-item-avatar
tile
size="80"
color="grey"
></v-list-item-avatar>
</v-list-item>
<v-card-actions>
<v-btn text>Button</v-btn>
<v-btn text>Button</v-btn>
</v-card-actions>
</v-card>
<v-pagination
v-model="page"
:length="headlines.length"
></v-pagination>
</v-app>
</div>
JS:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
page: 1,
headlines: ['headline1', 'headline2', 'headline3', 'headline4', 'headline5'],
subtitles: ['Greyhound divisely hello coldly fonwderfully', 'Greyhound divisely hello sunny wonderful', 'Flower expected coldly fonwderfully', 'Flower sunny hello', 'Greyhound flower']
}
},
})
What should I do?
Don't understand why you need the v-slot:items="props".
But your problem could be solved just by changing the following bindings,
<v-list-item-title class="headline mb-1"> {{ headlines[page - 1] }}</v-list-item-title>
<v-list-item-subtitle>{{ subtitles[page - 1] }}</v-list-item-subtitle>

Vuetify: show tooltip with a condition

I'm new to Vue.js and I hope with your help to understand scoped slots...
I would like to optimize my code, the tooltip must be visible on hover only if the label has more than 10 characters (or any other condition).
This works, but it is not optimized:
<v-btn>
<v-tooltip right v-if="slot.label.length > 20">
<template v-slot:activator="{on}">
<span class="text-truncate ml-1 mr-1" v-on="on">
{{slot.label}}
</span>
</template>
<span>{{slot.label}}</span>
</v-tooltip>
<span v-else class="text-truncate ml-1 mr-1">
{{slot.label}}
</span>
</v-btn>
I think the easiest way to achieve the desired effect without duplication is to use the disabled prop of v-tooltip.
new Vue({
el: '#app',
data () {
return {
slot: {
label: 'Label'
}
}
}
})
<link rel="stylesheet" href="https://unpkg.com/vuetify#1.5.16/dist/vuetify.css">
<script src="https://unpkg.com/vue#2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify#1.5.16/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-btn>
<v-tooltip right :disabled="slot.label.length < 10">
<template v-slot:activator="{on}">
<span class="text-truncate ml-1 mr-1" v-on="on">
Button: {{ slot.label }}
</span>
</template>
<span>Tooltip: {{ slot.label }}</span>
</v-tooltip>
</v-btn>
<v-btn #click="slot.label = 'Label'">Short</v-btn>
<v-btn #click="slot.label = 'Label label'">Long</v-btn>
</v-app>
</div>
The downside of this approach is that it still creates the tooltip even if it's disabled. The overhead isn't significant but if there are going to be a lot of tooltips then that might be a consideration.
There are various other ways to approach this but I can't think of any that are particularly simple. You could use a render function. That would allow you to write exactly what you want without any duplication but at the expense of needing to maintain a render function.
Sometimes you may want to show the tooltip when the underlying element is disabled. For eg: If a user has used all the resources in his account and then we need to ask the user to buy more resources. In such time insert an extra div and then add v-on onto to it.
<v-tooltip bottom :disabled="!noCandies">
<template v-slot:activator="{ on, attrs }">
<div v-on="on"> <!-- CREATE A DIV AND ADD V-ON HERE-->
<v-btn :disabled="noCandies" small class="mt-1" #click="useCandy">
Use candy
</v-btn>
</div>
</template>
<span>Buy more candies</span>
</v-tooltip>