Display Nested data in vuetify - laravel

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.

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>

How to use an object with Vuetify v-select?

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

Select 2 Wrapped component duplicated when loading options

I've created a wrapped vue component in laravel in order to wrap jQuery select2 element.
Based in this code.
When the values in select.options change, the select element is duplicated. Like the following image.
The selection only works in the second select.
I don't know what is the problem, I add below the code I have made and the content of the options variable.
select2.vue
<template>
<div>
<select>
<slot></slot>
</select>
</div>
</template>
<script>
export default {
name: "select2",
props: ['options', 'value'],
mounted: function () {
let vm = this
$(this.$el)
// init select2
.select2({ data: this.options })
.val(this.value)
.trigger('change')
// emit event on change.
.on('change', function () {
vm.$emit('input', this.value)
})
},
watch: {
value: function (value) {
// update value
$(this.$el)
.val(value)
.trigger('change')
},
options: function (options) {
// update options
$(this.$el).empty().select2({ data: options })
}
},
destroyed: function () {
$(this.$el).off().select2('destroy')
}
}
</script>
<style scoped>
</style>
blade file call
<select2 :options="select.options" v-model="select.value"></select2>
select.options data
[
{
"text": "Group 1",
"children": [
{
"id": 1,
"text": "Element 1"
},
{
"id": 2,
"text": "Element 2"
}
]
},
{
"text": "Group 2",
"children": [
{
"id": 3,
"text": "Element 3"
},
{
"id": 4,
"text": "Element 4"
}
]
}
]
I tried for a while to reproduce the problem you were having, without any success.
I noticed a couple of things that might help you:
this.$el refers to the div in your example, where as the examples I've seen use select.
Try and avoid using the same names for properties and variables, as this makes it confusing options: function (options) {
I've included a snippet below in case it helps.
Vue.config.productionTip = false;
Vue.config.devtools = false;
Vue.component("select2", {
template: "<select style='width: 100%'></select>",
props: ['options', 'value'],
mounted: function() {
let vm = this
$(this.$el)
.select2({
data: this.options
})
.val(this.value)
.trigger('change')
.on('change', function() {
vm.$emit('input', this.value)
})
},
watch: {
value: function(value) {
$(this.$el)
.val(value)
.trigger('change')
},
options: function(val) {
$(this.$el).empty().select2({
data: val
})
}
},
destroyed: function() {
$(this.$el).off().select2('destroy')
}
});
new Vue({
el: "#app",
data: () => {
return {
selected: null,
options: [{
"text": "Group 1",
"children": [{
"id": 1,
"text": "Element 1"
},
{
"id": 2,
"text": "Element 2"
}
]
},
{
"text": "Group 2",
"children": [{
"id": 3,
"text": "Element 3"
},
{
"id": 4,
"text": "Element 4"
}
]
}
]
}
},
methods: {
modifyOptions() {
this.options = [{
"text": "Group 1",
"children": [{
"id": 4,
"text": "Element 1"
},
{
"id": 6,
"text": "Element 2"
}
]
}];
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2#4.0.13/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2#4.0.13/dist/js/select2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<select2 :options="options" v-model="selected"></select2>
<div>
Selected: {{selected}}
</div>
<button type="button" #click="modifyOptions">Modify Options</button>
</div>
</div>

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 to implement Quill Emojis in vue2editor?

I tried to add Quill Emojis to editor but I am getting console error as
Uncaught ReferenceError: Quill is not defined
I am using Laravel 5.6 and vue js and definately new to vue and its components so I may sound silly to you but for the past 3 days I am searching on the google for the solution and even contacted author of vue2editor on github here is the link
This is what I have tried so far:
vue2editor.vue
<template>
<div id="app">
<vue-editor v-model="content"></vue-editor>
</div>
</template>
<script>
import { VueEditor, Quill } from 'vue2-editor';
import Emoji from 'quill-emoji/dist/quill-emoji';
Quill.register('modules/quill-emoji', Emoji);
export default {
name: 'vue2editor',
components: { VueEditor },
data() {
return {
content: "<h1>Some initial content</h1>",
editorSettings: {
modules: {
toolbar: {
container: [
[{'size': ['small', false, 'large']}],
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'sub' }, { 'script': 'super' }],
[{ 'indent': '-1' }, { 'indent': '+1' }],
[{ 'direction': 'rtl' }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }],
[{ 'font': [] }],
[{ 'align': [] }],
['clean'],
['link', 'image', 'video'],
['emoji'],
],
handlers: {
'emoji': function () {}
},
},
toolbar_emoji: true,
short_name_emoji: true,
textarea_emoji:true,
},
},
text: null,
};
},
};
</script>
I even tried the method mentioned by one of the user on github for Quill-Emoji, here is the link.
I came here with lots of hopes; if anyone here is to help me out, at least tell me what I am missing will be more than a help for me.
Quill.register({
'formats/emoji': Emoji.EmojiBlot,
'modules/short_name_emoji': Emoji.ShortNameEmoji,
'modules/toolbar_emoji': Emoji.ToolbarEmoji,
'modules/textarea_emoji': Emoji.TextAreaEmoji}, true);
you need register the model, add the up code to you code.
Edit:
//1) Add plugin to laravel mix
const mix = require('laravel-mix')
mix.webpackConfig(webpack => {
return {
plugins: [
new webpack.ProvidePlugin({
"window.Quill": "quill/dist/quill.js",
Quill: "quill/dist/quill.js"
})
]
};
});
//2 example vue file
<template>
<div class="mt-1">
<vue-editor
ref="editor"
v-model="content"
:editor-toolbar="customToolbar"
:editorOptions="editorSettings"
/>
</div>
</template>
<script>
import { VueEditor, Quill } from "vue2-editor";
import Emoji from "quill-emoji/dist/quill-emoji";
Quill.register("modules/emoji", Emoji);
export default {
components: {
VueEditor,
},
props: {
bubble: Object,
contentCol: {
type: String,
},
},
data() {
return {
edit: false,
content: "<b>Content is here</b>",
customToolbar: [["bold", "italic", "underline"], ["link"], ["emoji"]],
editorSettings: {
modules: {
"emoji-toolbar": true,
"emoji-textarea": true,
"emoji-shortname": true,
},
},
};
},
beforeDestroy() {},
};
</script>
<style src="quill-emoji/dist/quill-emoji.css"/>

Resources