Reputation: 207
I have this Vue app
var app = new Vue({
el: '#main',
delimiters: ['${', '}'],
data () {
posts: [
{
id: 1,
title: 'Post title 1',
description: 'Post description 1'
},
{
id: 2,
title: 'Post title 2',
description: 'Post description 2'
},
{
id: 3,
title: 'Post title 3',
description: 'Post description 3'
}
],
},
methods: {
getPostData: function (event) {
}
}
});
<div id="main">
<ul>
<li v-for="(post, index) in posts"><a @click="getPostData">${ post.title }</a></li>
</ul>
</div>
Here go description from clicked item
I want to click on an item in the list and display description from this item in #item-description div.
How I program this getPostData to grab description from an item on which I click.
Tnx
Upvotes: 3
Views: 6188
Reputation: 1006
In Vue 3
Script
<script>
export default {
data() {
return {
posts: [{
id: 1,
title: 'Post title 1',
description: 'Post description 1'
}, {
id: 2,
title: 'Post title 2',
description: 'Post description 2'
}, {
id: 3,
title: 'Post title 3',
description: 'Post description 3'
}],
currentId: null
};
},
methods: {
setCurrentId(id) {
this.currentId = id;
}
},
computed: {
currentPost() {
if (this.currentId !== null) {
const currentPostInArray = this.posts.filter(post => {
return post.id === this.currentId;
});
if (currentPostInArray.length === 1) {
return currentPostInArray[0];
}
}
return null;
},
currentDescription() {
if (this.currentPost !== null) {
return this.currentPost.description;
}
return null;
},
},
}
</script>
Markup
<template>
<div id="main">
<ul>
<li v-for="(post, index) in posts" :class="{ active: post.id === currentId }">
<a @click="setCurrentId(post.id)">${ post.title }</a>
</li>
</ul>
</div>
<div id="item-description">{{ currentDescription }}</div>
</template>
Upvotes: 0
Reputation: 16089
You need to somehow store the currently selected item or description. You could do this by calling a method from your template, passing by the item as a parameter. E.g. like this:
var app = new Vue({
el: '#main',
data() {
return {
posts: [{
id: 1,
title: 'Post title 1',
description: 'Post description 1'
}, {
id: 2,
title: 'Post title 2',
description: 'Post description 2'
}, {
id: 3,
title: 'Post title 3',
description: 'Post description 3'
}],
currentDescription: null
};
},
methods: {
setDescription(item) {
this.currentDescription = item.description;
}
}
});
<div id="main">
<ul>
<li v-for="(post, index) in posts">
<a @click="setDescription(post)">${ post.title }</a>
</li>
</ul>
</div>
<div id="item-description">{{ currentDescription }}</div>
If you want to asynchronously fetch new data on a click, you could fetch the data directly in the setDescription
method.
EDIT:
It's probably also better to store the ID of the post than the description itself. In this case, you have access to the whole post instead of just the description. You can then also check if the current <li>
is active and so on. Here is an example of this. In the example, I've used computed properties, which can then be accessed like regular properties. They are derived from the current state. So, currentPost
always gives you the currently selected post if the active ID is set. The currentDescription
then reads the description of the currentPost
. You can access these properties the same way as regular properties of the state.
var app = new Vue({
el: '#main',
data() {
return {
posts: [{
id: 1,
title: 'Post title 1',
description: 'Post description 1'
}, {
id: 2,
title: 'Post title 2',
description: 'Post description 2'
}, {
id: 3,
title: 'Post title 3',
description: 'Post description 3'
}],
currentId: null
};
},
methods: {
setCurrentId(id) {
this.currentId = id;
}
},
computed: {
currentPost() {
if (this.currentId !== null) {
const currentPostInArray = this.posts.filter(post => {
return post.id === this.currentId;
});
if (currentPostInArray.length === 1) {
return currentPostInArray[0];
}
}
return null;
},
currentDescription() {
if (this.currentPost !== null) {
return this.currentPost.description;
}
return null;
}
}
});
<div id="main">
<ul>
<li v-for="(post, index) in posts" :class="{ active: post.id === currentId }">
<a @click="setCurrentId(post.id)">${ post.title }</a>
</li>
</ul>
</div>
<div id="item-description">{{ currentDescription }}</div>
Just as a side note: Storing the whole post as a copy in the data instead of just the ID is not recommended. By using a computed property, you don't have to worry about this property, it will always be up to date. For instance, if you change the posts
array and remove the currently selected post from it, the currentPost
will lead to a null value, without updating anything else. Or in the case of changing the description: The computed property always gives you the correct item (with the updated description).
Upvotes: 2
Reputation: 13016
<div id="main">
<ul>
<li v-for="(post, index) in posts"><a @click="getPostData(post.description)">${ post.title }</a></li>
</ul>
</div>
methods: {
getPostData: function (postDesc) {
// you got the post Desc
}
}
Upvotes: 3