vuetify: Why are my radio buttons without value? - vue.js

I don't know why, but my radio buttons are without value.
I have the following json (my json), and I'm rendering the items as v-radio buttons inside a v-radio-group, my radio button label is item.description and value is item.id, but i can't get the value by v-model="picked", why this is happening?
when I inspect the page, this is the description of my radio buttons, it is not returning a value
<input aria-checked="false" id="input-90" role="radio" type="radio" name="radio-80" value="">
My json
CATEGORIES = [{
'title': 'vegetables:',
'items': [
{
'id': '19',
'description': 'asparagus',
}
]
},
{
'title': 'Fruits:',
'items': [
{
'id':'21',
'description': 'oranges',
},
{
'id': '22',
'description': 'Apples',
},
{
'id':'23',
'description': 'pears',
},
{
'id': '24',
'description': 'limes',
},
{
'id': '25',
'description': 'avocados',
},
]
},]
My template
<template>
<v-container>
<h3>Select the issue category:</h3>
<v-form >
<v-radio-group v-model="radios" :mandatory="false" >
<v-list dense v-for="category in categories" :key="category">
<v-list-item-title>{{category.title}}</v-list-item-title>
<br>
<v-radio v-for="item in category.items"
:key="item"
:label="item.description"
:value="item.id"
:name="items"
v-model="picked"></v-radio>
</v-list>
</v-radio-group>
</v-form>
</v-container>
</template>

The biggest problem is you're nesting two v-models. If you set a v-model on the <v-radio-group> you only set value on the <v-radio>, not v-model and it will select that value in the radio group model. If you want multiple values, you should either use checkboxes (which is the same as radios but the model holds the array of all checked items, not only one) or perhaps multiple radio groups, if that's the required app logic.
Another problem is you're not key-ing correctly. You should only use unique primitives as your keys, not objects. In your case, category.title and item.id make good key candidates, provided they are unique.
Also, you don't have an items defined.
Last, but not least, you seem to be using radios and picked in your template without defining them (at least in what you're showing here).
If you look in your console, Vue informs you about all of the above errors. The console is your friend. Here's your example, working. But I'm not sure if it has the desired logic of your app:
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
radios: [],
categories: [{
'title': 'vegetables:',
'items': [{
'id': '19',
'description': 'asparagus',
}]
},
{
'title': 'Fruits:',
'items': [{
'id': '21',
'description': 'oranges',
},
{
'id': '22',
'description': 'Apples',
},
{
'id': '23',
'description': 'pears',
},
{
'id': '24',
'description': 'limes',
},
{
'id': '25',
'description': 'avocados',
},
]
}
]
})
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-container>
<h3>Select the issue category:</h3>
<v-form>
<v-radio-group v-model="radios" :mandatory="false">
<v-list dense v-for="category in categories" :key="category.title">
<v-list-item-title>{{category.title}}</v-list-item-title>
<v-radio v-for="item in category.items"
:key="item.id"
:label="item.description"
:value="item.id"
:name="item.description"></v-radio>
</v-list>
</v-radio-group>
</v-form>
</v-container>
</div>

Related

Vuetify 2.6.12 - Problem with v-data-table inside v-dialog

In my application, when inserting a v-data-table inside a v-dialog, it is losing part of its CSS style.
Looking at the HTML, the class "v-application" and "v-application--is-ltr" are not being applied to v-dialog.
I need the same classes that are applied to all components inside ("v-application" and "v-application--is-ltr"), inside . Without these classes the is without application of some CSS. I imagine that even inside a v-dialog I could use a v-data-table and it would work
I've done several tests, like adding a v-row before the v-dialog, adding a v-container, putting v-col, removing v-col.
A lot of tests and I couldn't find a solution.
Has anyone gone through this problem?
Thank you very much in advance
Tables inside dialogs work just fine in Vuetify:
var app = new Vue({
el: '#app',
template: '#main',
vuetify: new Vuetify(),
data:
{
dlgVisible: false,
header:
[
{
value: 'fname',
text: 'First Name' ,
class: 'font-weight-bold text-subtitle-1',
},
{
value: 'lname',
text: 'Last Name' ,
class: 'font-weight-bold text-subtitle-1',
},
{
value: 'salary',
text: 'Salary' ,
class: 'font-weight-bold text-subtitle-1',
},
],
rows:
[
{
fname: 'John',
lname: 'Doe',
salary: 1000
},
{
fname: 'John',
lname: 'Doe',
salary: 1000
},
{
fname: 'John',
lname: 'Doe',
salary: 1000
},
],
},
});
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
</div>
<template id="main">
<v-app>
<v-btn color="primary" #click="dlgVisible = true">Show dialog</v-btn>
<v-dialog v-model="dlgVisible">
<v-card>
<v-card-title class="primary white--text py-2">Dialog</v-card-title>
<v-card-text>
<v-data-table :items="rows" :headers="header">
</v-data-table>
</v-card-text>
<v-card-actions class="justify-center">
<v-btn color="primary" #click="dlgVisible = false">Close</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-app>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>

Vuetify v-data-table custom filter for dropdown

I have a v-data-table that already has the :search and :sort-by enabled. I have now created a select where I pull in my status from VueX. Accepted, Rejected. What I want to do is not only search or sort but when selecting from the drop down, accepted only the accepted values display in the table.
<v-select
v-model="selectStatus"
label="Status"
:items="statusData"
item-value="id"
item-text="name"
return-object
#change="filterStatus"
/>
Is this the correct way to setup the filter?
methods: {
filterStatus () {
console.log('This is where I am planning to add my custom filter')
}
}
This is my statusData:
userStatus : [
{
id: 0,
name: "Accepted",
},
{
id: 1,
name: " Rejected",
},
];
Or better to pass in the data:
{ text: 'Status', value: 'status.name', filter: value => {}},
To disable certain values to be selected add a disabled property to your items.
var app = new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
items: [{
id: 0,
name: 'Accepted'
},
{
id: 1,
name: ' Rejected',
disabled: true
}
],
value: null
}
})
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-container>
Value : {{value}}
<v-select
v-model="value"
label="Status"
:items="items"
item-value="id"
item-text="name"
return-object
/>
</v-container>
</v-app>
</div>
Documentation : props-disabled

Split row-details into multiple row in bootstrap-vue

I am currently writing my first full-stack app. I am using bootstrap <b-table> to display content. On row-click, I expand the row to display nested data. Is there a way to iterate over the nested data and display it in nested rows within the parent b-table?
Currently, I can display the data, however it displays in a single row.
component.vue:
<template>
<div id="report-table" class="report-table">
<b-container>
<b-table striped hover sticky-header="100%"
:items="reports"
:fields="fields"
responsive="xl"
#click="clearRowClick"
#row-clicked="reports=>$set(reports, '_showDetails', !reports._showDetails)"
>
<template slot="row-details" slot-scope="row">
<template v-for="(proc, index) in row.item.Processes">
<b-tr :key=index>
<td>{{ proc.Name }}</td>
<td>{{ proc.Id }}</td>
</b-tr>
</template>
</template>
</b-table>
</b-container>
</div>
</template>
example
In the attached image, the bottom row has been clicked. The content is displayed within a single row, but I would like it to be separate rows, so later I can further click on them to display even more nested content.
data example:
{"_id": <id>, "Hostname": <hostname>, "Address": <address>, "Processes": [{"Name": ApplicationHost, ...}, {"Name": svchost, ...}]
If this is not possible, is there some other Bootstrap element that makes more sense to achieve what I want?
To strictly answer your question: no, a BootstrapVue <b-table>'s row-details row can't be expanded into more than one row.
The row-details row has severe limitations:
it's only one row
it's actually only one cell which, through use of colspan is expanded to the full width of the row (which means you can't really use the table columns to align the content of the row-details row).
But... this is web. In web, because it's virtual, virtually anything is possible. When it's not, you're doing-it-wrong™.
What you want is achievable by replacing rows entirely when a row is expanded, using a computed and concatenating the children to their parent row when the parent is in expanded state. Proof of concept:
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
data: () => ({
rows: [
{id: '1', name: 'one', expanded: false, children: [
{id: '1.1', name: 'one-one'},
{id: '1.2', name: 'one-two'},
{id: '1.3', name: 'one-three'}
]},
{id: '2', name: 'two', expanded: false, children: [
{id: '2.1', name: 'two-one'},
{id: '2.2', name: 'two-two'},
{id: '2.3', name: 'two-three'}
]}
]
}),
computed: {
renderedRows() {
return [].concat([...this.rows.map(row => row.expanded
? [row].concat(row.children)
: [row]
)]).flat()
}
}
})
tr.parent { cursor: pointer }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<tr v-for="row in renderedRows" :key="row.id"
#click="row.children && (row.expanded = !row.expanded)"
:class="{parent: row.children}">
<td>{{row.id}}</td>
<td>{{row.name}}</td>
</tr>
</table>
</div>
The example is rather basic (I haven't added BootstrapVue to it, nor have I used its fancy <b-table>), but it demonstrates the principle. Apply it to <b-table>'s :items.
One could even take it a step further and make it recursive, by moving the expansion logic into a method:
new Vue({
el: '#app',
data: () => ({
fields: ['id', { key: 'expanded', label: ''}, 'name'],
rows: [{
id: '1',
name: 'one',
expanded: false,
children: [
{ id: '1.1', name: 'one-one' },
{ id: '1.2', name: 'one-two' },
{
id: '1.3',
name: 'one-three',
expanded: false,
children: [
{ id: '1.3.1', name: 'one-three-one' },
{ id: '1.3.2', name: 'one-three-two' }
]
}
]
},
{
id: '2',
name: 'two',
expanded: false,
children: [
{ id: '2.1', name: 'two-one' },
{ id: '2.2', name: 'two-two' },
{ id: '2.3', name: 'two-three' }
]
}
]
}),
computed: {
items() {
return [].concat(this.rows.map(row => this.unwrapRow(row))).flat()
}
},
methods: {
unwrapRow(row) {
return row.children && row.expanded
? [row].concat(...row.children.map(child => this.unwrapRow(child)))
: [row]
},
tbodyTrClass(row) {
return { parent: row.children?.length, child: row.id.includes('.') }
}
}
})
.table td:not(:last-child) { width: 80px; }
.table .bi { cursor: pointer }
tr.child {
background-color: #f5f5f5;
font-style: italic;
}
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" />
<script src="//cdn.jsdelivr.net/npm/vue#2.6.14"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue-icons.min.js"></script>
<div id="app">
<b-table :items="items"
:fields="fields"
:tbody-tr-class="tbodyTrClass">
<template #cell(expanded)="{item}">
<b-icon v-if="item.children"
:icon="item.expanded ? 'chevron-up' : 'chevron-down'"
#click="item.expanded = !item.expanded" />
</template>
</b-table>
</div>
One approach (that I've personally used in the past) is simply to put a nested <b-table> inside your child row-details for child data, instead of trying to add them to the outer table.
It's also worth noting that adding child data rows to the outer table could be visually confusing if they don't look distinct enough from their parents.
Example:
new Vue({
el: '#app',
data() {
return {
reports: [{_id: 'ID#1', Hostname: 'Host1', Address: 'Addr1', Processes: [{Name: 'ApplicationHost', Id: '1'}, {Name: 'svchost', Id: '2'}]},
{_id: 'ID#2', Hostname: 'Host2', Address: 'Addr2', Processes: [{Name: 'ApplicationHost', Id: '3'}, {Name: 'svchost', Id: '4'}]},],
fields: ['Hostname', 'Address'],
}
},
});
<!-- Import Vue and Bootstrap-Vue -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap#4/dist/css/bootstrap.min.css" /><link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" /><script src="//unpkg.com/vue#latest/dist/vue.min.js"></script><script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<div id="app">
<b-table
bordered
striped
hover
:items="reports"
:fields="fields"
#row-clicked="reports=>$set(reports, '_showDetails', !reports._showDetails)"
>
<!-- <b-table> nested inside 'row-details' slot: -->
<template #row-details="row">
<b-table
bordered
:items="row.item.Processes"
:fields="['Name', 'Id']"
></b-table>
</template>
</b-table>
</div>

How to change the cursor default to pointer in Vuetify component

I want to change cursor default to pointer when active autocomplete in Vuetify.
I tried to make css code to change cursor.
but mouse drag on the autocomplete bottom, cursor change "text" style like "I beem". I want to show the "pointer " style.
I couldn't find out any idea Vuetify web site.
Does anyone have idea?
<template>
<v-card>
<v-container fluid>
<v-row
align="center"
>
<v-col cols="12">
<v-autocomplete
v-model="value"
:items="items"
dense
filled
label="Filled"
class="test_cursor"
></v-autocomplete>
</v-col>
</v-row>
</v-container>
</v-card>
</template>
<script>
export default {
data: () => ({
items: ['foo', 'bar', 'fizz', 'buzz'],
values: ['foo', 'bar'],
value: null,
}),
}
</script>
<style lang="scss" scoped>
.test_cursor{
cursor: pointer;
}
</style>
By default cursor is set to text (which appears as the "I-beam" you mention), but you can change the v-autocomplete's cursor by targeting the input in your CSS:
.test_cursor input {
cursor: pointer;
}
new Vue({
vuetify: new Vuetify(),
el: '#app',
data () {
return {
states: [
{ name: 'Florida', abbr: 'FL', id: 1 },
{ name: 'Georgia', abbr: 'GA', id: 2 },
{ name: 'Nebraska', abbr: 'NE', id: 3 },
{ name: 'California', abbr: 'CA', id: 4 },
{ name: 'New York', abbr: 'NY', id: 5 },
],
}
},
})
.test_cursor input {
cursor: pointer;
}
<script src="https://unpkg.com/vue#2.6.11"></script>
<script src="https://unpkg.com/vuetify#2.3.5"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify#2.3.5/dist/vuetify.css">
<v-app id="app">
<v-autocomplete
class="test_cursor"
:items="states"
item-text="name"
label="State"
></v-autocomplete>
</v-app>

Is it possible to change two values using v-model in select form in Vue?

I use v-select form where based on the item I pick I want to change two values at the same time.
Now I would like to do it this way but its not really possible as of now:
<v-select
:items="mapSelector"
item-text="text"
item-value1="valueA"
item-value2="valueB"
v-model1="data_plot[0].x"
v-model2-"data_plot[0].y"
></v-select>
Here is the list I connected to the select form:
mapSelector: [
{text: "A1", valueA: [3,2,3,4,1,2], valueB: [1]},
{text: "B2", valueB: [1,10,15,4,3,1], valueB:[2]}
],
data_plot that should be updated depending on the value that is selected looks like this:
data_plot: [{
x: [],
y: []}]
So for example when I select "A1" on the selector data_plot is updated accordingly:
data_plot: [{
x:[3,2,3,4,1,2],
y:[1] }]
So the question is: is there any way to use this and change two different values at the same time using v-model?
In this case a watcher is useful.
Let me show:
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: {
selected: '',
mapSelector: [{
text: "A1",
valueA: [3, 2, 3, 4, 1, 2],
valueB: [1]
},
{
text: "B2",
valueA: [1, 10, 15, 4, 3, 1],
valueB: [2]
}
],
data_plot: [{
x: [],
y: []
}]
},
watch: {
selected(newVal) {
this.data_plot[0].x = newVal.valueA
this.data_plot[0].y = newVal.valueB
}
}
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-container>
<v-row>
<v-col>
<v-select :items="mapSelector" v-model="selected" return-object>
</v-select>
</v-col>
</v-row>
<v-row>
<v-col>
data_plot[0].x: {{ data_plot[0].x }}<br /> data_plot[0].y: {{ data_plot[0].y }}<br />
</v-col>
</v-row>
</v-container>
</v-app>
</div>
The watcher reacts to changes in the selected data property, and sets the other data.
The only trick is that Vuetify's v-select requires the return-object prop.
Although a bit magical, v-model is essentially syntax sugar for
updating data on user input events, plus special care for some edge
cases.
...
v-model internally uses different properties and emits different
events for different input elements:
text and textarea elements use value property and input event;
checkboxes and radiobuttons use checked property and change event;
select fields use value as a prop and change as an event.
Source: https://v2.vuejs.org/v2/guide/forms.html
That's why you cannot have two v-models on an element: it's nothing else than an oninput and a value prop on input fields/selects/etc.
https://v2.vuejs.org/v2/guide/computed.html#Computed-vs-Watched-Property
i think u should have a look at computed property or watcher.
If u can make the question much more clearer would be more helpful
v-model1="data[0].x"
v-model2-"data[0].y"
This is wrong,and inside component data do you have an array data ?
<div class="value">
<select class="form-control" :required="true" v-model="value">
<option
v-for="option in mapSelector"
v-bind:value="option.text"
:key="option.id"
:selected="option.text == value"
>{{ option.text }}</option
>
</select>
</div>
new Vue({
el: "#app",
data: {
value: '',
variable:[] // which u need to change
},
watch: {
value(newVal) {
if(this.value == 'A1')
this.variable.push(10) // u can do ur stuff here
if(this.value == 'B1')
this.variable.push(10111) // u can do ur stuff here
}
}
})