Reputation: 265
I'm trying to make a wishlist where I use localstorage. When clicked on "add to wishlist" button the item is added to localstorage and then shows "remove from wishlist" button. I was trying to computed using filter and find ES6 but I might got it wrong. Here is my codesandbox-link and also below is the code. Please someone help thanks.
https://codesandbox.io/s/wishlist-ouuyw?file=/src/App.vue
<template>
<div id="app">
<h2>Total Selected: {{selectedEntries.length}}</h2>
<div v-for="entry in entries" :key="entry.id">
<div class="content-wrap">
<h3>{{entry.title}}</h3>
<button v-if="!checkExists" @click="addToWishlist(entry.id)">Add Wishlist</button>
<button v-else @click="removeToWishlist(entry.id)">Remove Wishlist</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: "App",
data(){
return{
entries: [
{
title: 'entry one',
id: 1
},
{
title: 'entry two',
id: 2
},
{
title: 'entry three',
id: 3
},
{
title: 'entry four',
id: 4
},
{
title: 'entry five',
id: 5
},
],
selectedEntries: JSON.parse(window.localStorage.getItem("wishlistItems")) || []
}
},
computed:{
checkExists(){
return this.entries.filter(entryItem => {
this.selectedEntries.find(selectedId => {
return entryItem.id === selectedId.id
})
})
}
},
methods:{
addToWishlist(entryId){
this.selectedEntries.push({ id: entryId });
window.localStorage.setItem("wishlistItems", JSON.stringify(this.selectedEntries));
console.log("Clicked>>>", this.selectedEntries)
}
}
};
</script>
<style scoped>
.content-wrap{
display: flex;
border: 1px solid;
margin: 5px;
padding: 5px;
align-items: center;
}
.content-wrap h3{
text-transform: capitalize;
width: 30%;
}
.content-wrap button{
border: none;
padding: 10px 20px;
height: 30px;
background-color: #1d9a61;
color: #fff;
font-size: 16px;
cursor: pointer;
line-height: .7
}
</style>
Upvotes: 1
Views: 560
Reputation: 4506
You can create a method which checks if the object is present in the selected objects array and shows the respective buttons accordingly. I'm not sure why you only wish to keep it as a computed
property. Because computed properties are not really used for computing values of array elements on the fly. Computed
property methods don't take in an argument, so its not directly possible. Computed properties are used more for single values defined in the data
property. Look at their official documentation.
So if you want to go with a computed
property only, then you will have to create a computed
property for fetching the matching
items and then create another method that basically takes in this matching items array and the current entry.id
and returns a boolean. But this is not a good solution. Ideal solution would be to just have it as a method that takes the current entry.id
as an argument as shown below.
.
<template>
<div id="app">
<h2>Total Selected: {{selectedEntries.length}}</h2>
<div v-for="entry in entries" :key="entry.id">
<div class="content-wrap">
<h3>{{entry.title}}</h3>
<button v-if="!checkExists(entry.id)" @click="addToWishlist(entry.id)">Add Wishlist</button>
<button v-else @click="removeToWishlist(entry.id)">Remove Wishlist</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: "App",
data(){
return{
entries: [
{
title: 'entry one',
id: 1
},
{
title: 'entry two',
id: 2
},
{
title: 'entry three',
id: 3
},
{
title: 'entry four',
id: 4
},
{
title: 'entry five',
id: 5
},
],
// selectedEntries: JSON.parse(window.localStorage.getItem("wishlistItems")) || [],
selectedEntries: [{
title: 'entry one',
id: 1
},
{
title: 'entry two',
id: 2
}],
}
},
methods:{
addToWishlist(entryId){
this.selectedEntries.push({ id: entryId });
window.localStorage.setItem("wishlistItems", JSON.stringify(this.selectedEntries));
console.log("Clicked>>>", this.selectedEntries)
},
checkExists(entryId){
return this.selectedEntries.find(item => item.id === entryId);
}
}
};
</script>
<style scoped>
.content-wrap{
display: flex;
border: 1px solid;
margin: 5px;
padding: 5px;
align-items: center;
}
.content-wrap h3{
text-transform: capitalize;
width: 30%;
}
.content-wrap button{
border: none;
padding: 10px 20px;
height: 30px;
background-color: #1d9a61;
color: #fff;
font-size: 16px;
cursor: pointer;
line-height: .7
}
</style>
Upvotes: 2