Vuetify How to update component data when list item group select changed - vue.js

I'm using v-list-item-group and I want to show data in another component when the list item is selected. clear data when I unSelect item, and change data when I click on another list item
how can I possibly do it in vue?
the list item which I select:
Here I want to clear curr step data if the list.eid changed or when index changed
<v-list-item-group v-model="wfs">
<v-list-item v-for="(list,index) in workflowStepsList" :key="index"
#click="getWorkflowStep(list.eid)">
<v-list-item-action-text class="pe-4"> {{ index+1 }}</v-list-item-action-text>
<v-list-item-content v-if="!list.title">
{{ list.stepTitle }}
</v-list-item-content>
<v-list-item-content v-if="!list.stepTitle">
{{ list.title }}
</v-list-item-content>
<v-list-item-icon>
<v-icon small color="red">mdi-delete</v-icon>
</v-list-item-icon>
</v-list-item>
<v-list-item v-if="!workflowStepsList.length">
مرحله ای وجود ندارد
</v-list-item>
</v-list-item-group>
and the list I render data based on what I selected:
<v-card>
<v-card-title class="bg-success text-white d-flex justify-space-between">
مرحله فعلی
<add-curr :getSteps="getSteps"/>
</v-card-title>
<v-card-text>
<v-list>
<v-list-item-group class="v-list-item-group" v-model="stepId">
<v-list-item
v-if="!currStep.length"
class="text-muted"
>
یک مرحله انتخاب کنید
</v-list-item>
<v-list-item
v-for="(element) in currStep"
:key="element.eid"
v-show="element.eid !== null"
>
{{ element.title }}
</v-list-item>
</v-list-item-group>
</v-list>
</v-card-text>
</v-card>
the function:
async getWorkflowStep(weid) {
await this.$store.dispatch("axiosGet",
{url: `folder/api/workflow-steps/${weid}`, params: {workflowId: this.id}}).then(response => {
if (response.status === 'error') return
this.workflowStepsObj = response.data.data
const x = response.data.data
const curr = {
title: x.stepTitle,
eid: x.stepEid
}
this.currStep.push(curr)
})
},

I just added an another component and passing the model value as a prop in that component.
Live Demo :
Vue.component('another-component', {
props: ['val'],
template: '<h3>{{ val }}</h3>'
});
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
items: [
{ text: 'Inbox' },
{ text: 'Star' },
{ text: 'Send' },
{ text: 'Drafts' }
],
model: 1,
}),
});
<script src="https://unpkg.com/vue#2.x/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify#2.6.12/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify#2.6.12/dist/vuetify.min.css"/>
<div id="app">
<v-list>
<v-list-item-group v-model="model">
<v-list-item v-for="(item, i) in items" :key="i">
{{ item.text }}
</v-list-item>
</v-list-item-group>
</v-list>
<another-component :val="items[model].text"></another-component>
</div>

You can either use store value and watch it from the component you want to track the change (it is possible to watch store properties if they change). If using vuex: https://vuex.vuejs.org/api/#watch
Or you can use emits and listen to the change on desired component, if there's depth issue for the emit you could pass emits on top level using (v-on="$listeners"): https://v2.vuejs.org/v2/guide/components-custom-events.html#Binding-Native-Events-to-Components
Since there's no statement about Vue or Vuetify version, inferring it is the 2nd version.
Sometimes when using Vuetify or UI libraries we may forget the features that Vue provides. Despite Vuetify having built-in features most probably they can be overridden by implementing yours on top of them.

Related

After adding 1 item to TODO app fails when I just type on text field, How to fix it?

this might be stupitest question to ask but I just can't understand why this is happening , I am trying to Build simple TODO app with Nuxt Js with Vuex, When I add one Item it works fine and displays, after that if I just type something on text field app failds and gives error
"Error: [vuex] do not mutate vuex store state outside mutation handlers."
Here is index.vue file
<template>
<v-main>
<v-row justify="center" class="py-10">
<h1 class="teal--text">NUXT TODO APP</h1>
<v-col cols="12" md="10">
<v-text-field type="text" outlined v-model="item.text"> </v-text-field>
<v-btn color="teal" x-large class="mt-3" #click="addItem">Add</v-btn>
</v-col>
<v-col cols="8">
<h1 v-if="items.length <= 0">No Data Found</h1>
<v-list v-else>
<v-list-item v-for="item in items" :key="item.id" class="my-5">
<v-list-item-content>
<v-list-item-title>{{ item.text }}</v-list-item-title>
</v-list-item-content>
<v-list-item-action class="d-flex flex-row">
<v-btn color="teal"> Edit </v-btn>
<v-btn color="error" class="mx-5"> Delete </v-btn>
</v-list-item-action>
</v-list-item>
</v-list>
</v-col>
</v-row>
</v-main>
</template>
<script>
export default {
computed: {
items() {
return this.$store.state.items;
},
},
data: () => ({
item: {
text: "",
},
}),
methods: {
addItem() {
this.$store.commit("addItem", this.item);
},
},
};
</script>
And here is index.js file for Vuex
export const state = () => ({
items: [],
});
export const mutations = {
addItem(state, payload) {
state.items.push(payload);
},
};
please guide me what the hell I am missing here.
Thank You.

whoe to solve this proplem :updating a chiled component in vuejs update all the other childeren?

I want to update the likes for the specific comment
this is the parent component Commnet.vue
<template>
<v-list class="list" color="white" three-line>
<template v-for="cmnt in comments" class="mb-2">
<v-card color="transparent" class=" text-no-wrap" :key="cmnt._id">
<v-list-item class="item" :key="cmnt._id">
<v-list-item-avatar>
<v-img :src="cmnt.author.image"></v-img>
</v-list-item-avatar>
<v-list-item-content class="black--text">
<v-list-item-title>{{
cmnt.author.first_name + " " + cmnt.author.last_name
}}</v-list-item-title>
<v-list-item-subtitle class="black--text" v-html="cmnt.comment">
{{ cmnt.comment }}
</v-list-item-subtitle>
</v-list-item-content>
<v-card class="like-count">
<v-icon color="blue">mdi-thumb-up </v-icon>
<Likes :_id="cmnt._id"/>
</v-card>
</v-list-item>
</v-card>
<v-card
:key="cmnt._id"
outlined="true"
color="transparent"
class="ml-6"
>
</template>
and this is the child component inside comment component it has it is own state completely separated form the parent.
Like.vue
<template>
<div>
<v-card >
</v-card>
{{likes.length}}
</div>
</template>
<script>
import axios from "axios";
import io from "socket.io-client";
export default {
name:"Likes",
created:async function(){
axios.get(`comment/${this._id}`)
.then(results=>{
if (results.data){
this.likes =results.data;
}
})
.catch(err=> console.log(err));
let url = "";
if (process.env.NODE_ENV === "production") {
url = "/";
} else {
url = "http://localhost:5000";
}
this.socket = io(url);
this.socket.on("receive-like",async (data)=>{
console.log(data)
this.new_like= data;
console.log(this.new_like)
const el = this.likes.find(el => el._id === this.new_like._id)
if (el){
const index = this.likes.indexOf(el);
this.$forceUpdate()
return this.likes.splice(index,1)
}else{
this.likes.push(this.new_like);
console.log(this.likes)
this.$forceUpdate()
}
})
},
mounted:async function(){
},
props:{
_id:{
type: String
}
},
data:()=>({
user:{},
likes:[],
new_like:{}
}),
computed:{
},
}
</script>
so when clicking like the new like object get pushed to the array of likes for the concerned comment but likes for all comments get updated at ones.
in case somebody is wondering I just made adding the new like object conditional
if(data.comment._id === this._id)

How do I overcome error 'Avoid using JavaScript keyword as "v-on" value'

How do I get rid of this error in my App.vue component?
Failed to compile.
./src/App.vue
Module Error (from ./node_modules/eslint-loader/index.js):
C:\xampp2\htdocs\exchproto\src\App.vue
15:69 error Avoid using JavaScript keyword as "v-on" value: "" vue/valid-v-on
✖ 1 problem (1 error, 0 warnings)
I tested the whole code (including sub-components) with CDN pull of vuejs/vuetify css/js etc and all worked well. This error only comes up as I am breaking down the code into components and doing everything by "yarn install". Been poking at it for some time with no luck.
<template>
<v-app>
<v-app-bar app>
<v-app-bar-nav-icon #click="drawer = !drawer"></v-app-bar-nav-icon>
<v-spacer></v-spacer>
<v-menu :offset-y="true">
<template v-slot:activator="{ on }">
<v-btn icon v-on="on">
<v-icon>mdi-dots-horizontal</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item v-for="(item, i) in rightMenuitems" :key="i" #click="">
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-app-bar>
<!--router-view></!--router-view-->
</v-app>
</template>
<script>
export default {
name: 'App',
components: {},
data() {
return {
drawer: false,
rightMenuitems: [
{ title: 'Choice 1' },
{ title: 'Choice 2' },
{ title: 'Choice 3' },
{ title: 'Choice 4' }
],
}
}
}
</script>
You can't have an empty #click="" You must have the click point to a function:
<v-list-item
v-for="(item, i) in rightMenuitems"
:key="i"
#click="doSomething($event, i)"
>
<v-list-item-title>
{{ item.title }}
</v-list-item-title>
</v-list-item>
// ...
methods: {
someFunction(event, i) {
console.log("clicked item " + i);
}
}
// ...
Remove 'click event' and add to property in v-list-item where v-for is being used.
Note:
You can bind links with the to props, and also links in every objects of rightMenuitems.
Here is an example:

How to set Vuetify pagination on list

With vuetify, I am trying to set <v-pagination> on a <v-list-item> but I don't see how to bind my items (n in notification) to the pagination. Does it need an extra function? Most of the documentation I found was with vuetify tables.
<template>
<div>
<v-card
class="mx-auto"
max-width="300"
tile
>
<v-list rounded>
<v-subheader>NOTIFICATIONS</v-subheader>
<v-list-item-group color="primary">
<v-list-item
v-for="(n, i) in notification"
:key="i"
>
<v-list-item-content>
<v-list-item-title v-text="n.payload"></v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-pagination
v-if="pages > 1"
v-model="pagination.page"
:length="pages"
></v-pagination>
</v-list-item-group>
</v-list>
</v-card>
</div>
</template>
<script>
export default {
name: "status",
data() {
return {
pagination: {
page: 1,
total: 0,
perPage: 0,
visible: 3
},
notification: [],
}
},
computed: {
pages () {
Math.ceil(this.notification.length / 3)
}
}
}
</script>
How do I set the number of items displayed by page?
you can use the pagination component's v-model to get a list of items to display.
here's an example
<div id="app">
<v-app id="inspire">
<div class="text-center">
{{ visiblePages }}
<v-pagination
v-model="page"
:length="Math.ceil(pages.length/perPage)"
></v-pagination>
</div>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
page: 1,
perPage: 4,
pages: [0,1,2,3,4,5,6,7,8,9,10,11,12,13]
}
},
computed: {
visiblePages () {
return this.pages.slice((this.page - 1)* this.perPage, this.page* this.perPage)
}
}
})
https://codepen.io/scorch/pen/RwwGKrQ
you can then pass the visiblePages to you item list.

Enable/Disable Button based on selected value

I have a button in my view
<v-menu offset-y>
<v-btn>
Action Items
</v-btn>
<v-list>
<v-list-tile
v-for="(item, index) in items"
:key="index"
:disabled="item.disabled"
>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
<v-data-table
v-model="selected">
my data looks like
<script>
export default {
data: () => ({
selected: [],
items: [
{ title: 'Delete',disabled:false},
],
...
i am trying to enable or disable the v-list-tile based on whether the selected array has any values.
i tried something like:
items: [
{ title: 'Delete',disabled:this.selected.length=0},
],
but it gives me the following error:
[Vue warn]: Property or method "selected" is not defined on the instance but referenced during render.
please help me to resolve this issue.
I would say rather than have a disabled property on your model, you can have it as a computed property like so:
computed: {
disabled() {
return this.selected.length < 1; // or === 0
}
}
Then use the disabled property in your component.
<v-list-tile v-for="(item, index) in items"
:key="index"
:disabled="disabled">
<v-list-tile-title>
{{ item.title }}
</v-list-tile-title>
</v-list-tile>
PS: that props is passed into your v-list-tile as disabled property of that element. I am not sure if a custom component will be disabled (otherwise you know you'll use it on a real html element)