How to use an object with Vuetify v-select? - vuetify.js

Can I use an object for the items prop with Vuetify v-select ?
If yes, how to set the object key as item-text and object value as item-value ?

No. But is easy, you convert the object to an array using the default text and value:
<v-select
v-model="selected"
:items="Object.keys(items_obj).map((key) => ({text:key, value:items_obj[key]}))"
/>
May be better to create a computed property or a method, or even your custom component if you do this a lot

You can use this code to use object in v-select
<template>
<v-select
v-model="select"
:items="items"
item-text="state"
item-value="abbr"
label="Select"
return-object
single-line
></v-select>
</template>
<script>
export default {
data () {
return {
select: { state: 'Florida', abbr: 'FL' },
items: [
{ state: 'Florida', abbr: 'FL' },
{ state: 'Georgia', abbr: 'GA' },
{ state: 'Nebraska', abbr: 'NE' },
{ state: 'California', abbr: 'CA' },
{ state: 'New York', abbr: 'NY' },
],
}
},
}
</script>
Visit this link to read more about it https://vuetifyjs.com/en/components/selects/#custom-text-and-value

Related

Vue.JS Bootstrap-vue Tables - API Laravel - Relationship

I am using b-table (Bootstrap-vue) with API Laravel.
This is the vue code:
<TableCli
:items="items"
:fields="fields"
:rows="rows"
:perPage="perPage">
</TableCli>
.
data: function () {
return {
mode: "save",
item: {},
items: [],
paises: [{}],
checked: 1,
page: 1,
perPage: 10,
fields: [
{ key: "id", label: "Código", sortable: true },
{ key: "name", label: "Name", sortable: true },
{ key: "tva", label: "TVA", sortable: true },
{ key: "country_id", label: "Country", sortable: true},
{ key: "cp", label: "CP", sortable: true },
{ key: "city", label: "City", sortable: true },
{ key: "address", label: "Address", sortable: true },
{
key: "status",
label: "Status",
sortable: true,
formatter: (value) => (value ? "Yes" : "No"),
},
{ key: "actions", label: "Actions" }
],
};
Methods:
methods: {
loadCli() {
const url = `${baseApiUrl}/api/cli`;
axios.get(url).then((res) => {
this.items = res.data;
});
},
loadCountrys() {
const url = `${baseApiUrl}/api/country`;
axios.get(url).then(res => {
this.country = res.data
})
},
My table returns the country id, how do I return the country name?
Another question, how do I add an action button in the Actions column?
The button to edit and delete.
I think this snippet answers your questions. The main idea is using slot for b-table.
new Vue({
el: '#app',
data() {
return {
table_fields: [
{
key: "title",
label: "Title"
},
{
key: "user",
label: "User"
},
{
key: "id",
label: "Detail Button"
}
],
page_contents: [
{
id: "title-id-1",
title: "title 1",
user: {
id: "user-id-1",
name: "name 1",
},
}
]
}
},
methods: {
do_sth(id) {
console.log(id)
}
}
})
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap#4.5.3/dist/css/bootstrap.min.css" />
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.min.js"></script>
<div id="app">
<b-table-lite striped small hover :items="page_contents" :fields="table_fields">
<template #cell(id)="data">
<b-button size="sm" #click='do_sth(data.value)'>Detail Button</b-button>
</template>
<template #cell(user)="data">
<span> {{ data.value.id }} </span>
<span> || </span>
<span> {{ data.value.name }} </span>
</template>
</b-table-lite>
</div>

Display Nested data in vuetify

Hi guys new coder here... just need some help.
I want to display a nested data in vue having vuetify
here is my data:
{
"data": [
{
"id": 1,
"customer": {
"id": 88,
"name": "David Zulauf III",
"mobile": "240-545-5366 x7059"
},
"item": "rau",
"qty": "4",
"fit": {
"name": "fourth"
},
"shop": "Metz, Cole and McKenzie"
},
],
}
I am using Laravel as a back end. not sure about the proper term but I used the Laravel resource functionality to somewhat relate my table together that's why I got this nested data.
this is my vue file and I used vuetify data tables to display the above data
<script>
export default {
data () {
return {
search: '',
dialog: false,
edit:false,
items:[],
headers: [
{text: 'customer',align: 'start',sortable: false,value: 'customer',},
{ text: 'item', value: 'item' },
{ text: 'qty', value: 'qty' },
{ text: 'fit', value: 'fit' },
{ text: 'shop', value: 'shop' },
],
}
},
created(){
this.fetchItems();
},
methods: {
fetchItems(){
axios.get('api/item')
.then(res=>{
this.items = res.data.data;
});
}
}
}
</script>
<template>
<v-card>
<v-card-title>
Items
<v-spacer></v-spacer>
<v-btn depressed color="primary" #click="addNew"> ADD</v-btn>
<v-spacer></v-spacer>
<v-text-field
v-model="search"
append-icon="mdi-magnify"
label="Search"
single-line
hide-details
></v-text-field>
</v-card-title>
<v-data-table :headers="headers" :items="items" :search="search"></v-data-table>
</v-card>
</template>
thank you for the help guys.
You could provide a path to that nested properties like :
headers: [
{text: 'name',align: 'start',sortable: false,value: 'customer.name',},
{text: 'mobile',align: 'start',sortable: false,value: 'customer.mobile',},
{ text: 'item', value: 'item' },
{ text: 'qty', value: 'qty' },
{ text: 'fit name', value: 'fit.name' },
{ text: 'shop', value: 'shop' },
],
Also you can completely customise your Datatable using "item" slot and others, you can look through Vuetify documentation for getting more details.
It can be more complicated but helps when you need to get both values in same column or get different nested levels in one column.

Change base language of vuetify UI components

For example :
Shown in the documentation : Vuetify documentation
We have the "Items per page" displayed in english. If i want to change the text or just select the language to translate it to french for instance, how can i do that ?
Despite not being explicitly mentioned the locale prop seems to be present in all the vuetify components so you can use it. See my example.
src/components/my-datatable.vue
<template>
<v-data-table
:headers="headers"
:items="desserts"
:items-per-page="5"
locale="fr"
></v-data-table>
</template>
src/plugins/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
import fr from 'vuetify/src/locale/fr.ts'
Vue.component('my-component', {
methods: {
changeLocale () {
this.$vuetify.lang.current = 'fr'
},
},
})
export default new Vuetify({
lang: {
locales: { fr },
current: 'fr',
},
})
<v-data-table :rows-per-page-items="rowOptions" :rows-per-page-text="rowPageText">
</v-data-table>
data () {
return {
rowOptions: [
5,
15,
25,
{ text: "$vuetify.dataIterator.rowsPerPageAll", value: -1 }
],
rowPageText: "Objets par page:"
}
}
Or you may want to check the internationalization documentation
Updated answer => 2022
if you are like me and don't want to set up internationalization in vuetify's config, do this instead:
(note: I have set up #nuxtjs/i18n and have access to 'this.$t()' throughout my application. you can freely use any other text instead of them.)
for headers it's easy:
<v-data-table
:headers="headers"
>
data() {
headers: [
{ text: this.$t('id'), value: 'id' },
{ text: this.$t('status'), value: 'state' },
{ text: this.$t('title'), value: 'title' },
{ text: this.$t('price'), value: 'amount' },
{ text: this.$t('date'), value: 'time' },
{ text: this.$t('gateway'), value: 'gateway' },
]
}
and for footer props:
<v-data-table
:footer-props="footerProps"
>
data() {
footerProps: {
disableItemsPerPage: true,
itemsPerPageText: this.$t('itemsPerPageText'),
itemsPerPageAllText: this.$t('all'),
}
}
this was enough for me cause my table was rather simple.
for more footer props refer to the documentation:
https://vuetifyjs.com/en/api/v-data-footer/#props

How can I allow members to access and edit profile page only?

I've created an admin dashboard for administrating members. As an admin I can login in do everything.
I need also to allow these members (regular users) to login, be redirected to their profile page and be able to edit a subset of their properties.
I've searched through the documentation but have been unable to figure how best to accomplish this.
Is there a standard way, and if there is how can do this?
All what you need to manage user permissions on your dashboard is available on the Authorization section of the documentation.
Firstly, at the authentication step, you have to set the current user permission (basically a string of your choices, given by the API and/or stored inside the local storage for example: user, admin, user_X, etc):
if (type === AUTH_GET_PERMISSIONS) {
const { role, id } = params;
return Promise.resolve(`${role}_${id}`);
}
Then, you can check this permission inside your resource declaration:
export const UserEdit = ({ ...props }) =>
<Edit title={<UserTitle />} {...props}>
{permissions =>
<TabbedForm defaultValue={{ role: 'user' }}>
<FormTab label="user.form.summary">
<DisabledInput source="id" />
{permissions === `user_${props.record.id}` &&
<TextInput source="name" validate={required} />
}
</FormTab>
</TabbedForm>}
</Edit>;
And you can also restrict an entire resource to administrators:
<Admin
restClient={restClient}
authClient={authClient}
>
{permissions => [
// Restrict access to the remove view to admin only
<Resource
name="customers"
list={UserList}
edit={UserEdit}
remove={permissions.startsWith('admin') ? UserDelete : null}
/>,
// Only include the categories resource for admin users
permissions.startsWith('admin')
? <Resource name="categories" list={CategoryList} edit={CategoryEdit} />
: null,
]}
</Admin>
You could also try to use my ra-component-factory that tackles those problems in a very elegant way: https://github.com/zifnab87/ra-component-factory it is now listed in contributions of admin-on-rest (https://github.com/marmelab/admin-on-rest/blob/master/docs/Ecosystem.md)
Here is the general skeleton of configuration - it helps you set fields as not visible or read-only, menu-item visibility, action button visibility and even tab arrangement per role and per action.
export default {
props: {
id: {
input: (<TextInput source="id"/>),
field: (<TextField source="id"/>),
},
name: {
input: (<TextInput label="Name" source="name"/>),
field: (<TextField label="Name" source="name"/>),
},
date: {
input: (<DateInput source="date" parse={dateParser} label="Post Date"/>),
field: (<DateField source="date" type="date" label="Post Date"/>),
},
dateGte: { //date Greater than equal
input: (<DateInput source="dateGte" parse={dateParser} label="Date from"/>),
},
dateLte: { // date Less than equal
input: (<DateInput source="dateLte" parse={dateParser} label="Date to"/>),
},
author: {
input: <ReferenceInput label="Author" source="author" reference="authors" allowEmpty>
<SelectInput optionText="name" translate={false}/>
</ReferenceInput>,
field: <ReferenceField label="Author" source="author" reference="authors" sortable={false} linkType={false} allowEmpty={true}>
<ChipField source="name"/>
</ReferenceField>
},
},
role1: {
create: {
props: ["name", "author", "date"],
action: true
},
edit: {
props: ["_id", "name", "author", "date"],
action: true
},
list: {
props: ["id", "name", "author", "date"],
action: true
},
filter: {
props: ["q", "id", "author", "dateGte", "dateLte"],
action: true
},
show: {
props: ["id", "name", "author"],
action: true
},
search: {
action: true
},
delete: {
action: true
},
},
role2: {
create: {
props: [],
action: false
},
edit: {
props: [],
action: false
},
list: {
props: ["id", "name", "author", "date"],
action: false
},
filter: {
props: ["q", "id", "author", "dateGte", "dateLte"],
action: true
},
show: {
props: ["id", "name", "author"],
action: true
},
search: {
action: true
},
delete: {
action: false
},
}
}

Vue.js filterBy array as searchText

In vue.js how can one filterBy multiple properties?
Consider following data structure.
new Vue({
el: body,
data: {
items: [
{name: 'thing1', age: 5, properties: [
{ name: 'color', value: 'black'},
{ name: 'weight', value: 3}
]},
{name: 'thing2', age: 3, properties: [
{ name: 'length', value: 4},
{ name: 'weight', value: 4}
]},
{name: 'thing3', age: 9, properties: [
{ name: 'color', value: 'black'},
{ name: 'length', value: 20}
]}
],
property: ''
}
});
Now, one can easily filterBy single property, like so:
<input v-model="property" />
<div v-for="item in items | filterBy property in 'properties'">
{{ item.name }}
</div>
However, if I would like to search by more than one property.
e.g. to get thing3, I have tried this, but, of course, this does not work.
property: ['black', 20]
Do I need to implement some sort of dynamic filterBy chaining? I do not know how many properties there will be.
Crude way to accomplish this would be to create filterBy for each distinct property in current items array and keeping most of them empty. Something like this.
new Vue({
el: body,
data: {
items: [],
property1: '',
property2: '',
property3: '',
...
propertyN: ''
}
});
And this:
<div v-for="item in items | filterBy property1 in 'properties'|
filterBy property2 in 'properties'|
filterBy property3 in 'properties'|
...
filterBy propertyN in 'properties'">
{{ item.name }}
</div>
But that feels wrong to do.
Seems like custom function is the only viable option.
filters: {
myProperty: function(items, properties = this.properties) {
if (!properties || properties.length === 0) {
return items;
}
return this.recursiveFilter(items, propeties, 0);
}
},
methods: {
recursiveFilter: function(items, properties, currentPosition) {
if (currentPosition+1 > properties.length)
return items;
var new_items;
new_items = items.filter(function(item) {
for (row of item.properties) {
if (row.value == properties[currentPosition])
return true;
}
});
return this.recursiveFilter(new_items, properties, currentPosition+1);
}
}

Resources