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
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
Share Improve this question edited Nov 21, 2018 at 10:43 Yashwardhan Pauranik 5,5865 gold badges45 silver badges75 bronze badges asked Nov 21, 2018 at 10:11 NikolaNikola 2071 gold badge4 silver badges18 bronze badges 3- Would you please describe what exactly is not working as expected? – kleinfreund Commented Nov 21, 2018 at 10:12
- It will be useful to understand what is not working if you add the code you tried so far – Plastic Commented Nov 21, 2018 at 10:13
- For now everything is working. But how i program this getPostData to grab description from item on which I click. – Nikola Commented Nov 21, 2018 at 10:15
3 Answers
Reset to default 3<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
}
}
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 puted 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;
}
},
puted: {
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 remended. By using a puted 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 puted property always gives you the correct item (with the updated description).
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;
}
},
puted: {
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>