How to target object for v-for - vuejs2

created() {
const currentActivity = this.$store.getters.currentActivity
const activity = currentActivity.activity
}
The object I want to loop through its properties, is activity.
Its content displays fine in the console.
Inside the template I have:
<ul>
<li v-for="value in activity" :key="value.id">
{{ value.activity.activityName }}
{{ value.related_Activity }}
</li>
</ul>
Inside data():
return {
activity: activity
}
But the console says: "activity is not defined"
I tried this.activity, no errors in console but it doesn't display anything on the page.
So, how to refer the the activity object?

Instead of using const activity = currentActivity.activity
change it to this.activity = currentActivity.activity and then in your data return { activity: [] }

Very close to #RenatoManalili answer.
this.currentActivity = currentActivity did the job.
Also, I update the template code as so:
<ul v-for="value in currentActivity" :key="value.id">
<li>{{ value.activity.activityName }}</li>
<li>{{ value.related_activity }}</li>
</ul>
``` because it wasn't properly displaying the list.
Thank you.

Related

How to fix simple error in moving ".slice()" into setup() as a computed function?

I'm using Vuejs3 and trying to move .slice(0,3) (limits v-for to 3) into a computed function in the setup(), in order to limit the number of elements in a v-for (that happens to be nested in another v-for).
Everything works as intended before the change, using the following code:
<ul class="mt-4">
<div v-for="review in prime.allReviews" :key="review">
<li v-for="pro in review.propPros.slice(0, 3)" :key="pro">
{{ pro }}
</li>
</div>
</ul>
When I try to move the slice(0, 3) into the setup() as a computed function, per a dozen suggestions it's best practice to do so, the DOM goes blank. Here's the code causing the problem:
<ul class="mt-4">
<div v-for="review in prime.allReviews" :key="review">
<li v-for="pro in limitedPros" :key="pro">
{{ pro }}
</li>
</div>
</ul>
And in setup():
const limitedPros = computed(() => {
return review.propPros.slice(0, 3);
});
...
return {
limitedPros,
};
Thanks for any help!
Try to pass review to function, without computed property:
(When you want to loop review you need to know which one)
const { ref } = Vue
const app = Vue.createApp({
setup() {
const prime = ref({allReviews: [{propPros: [1,2,3,4,5]}, {propPros: [6,7,8,9]}]})
const limitedPros = (review) => {
return review.propPros.slice(0, 3);
};
return { limitedPros, prime };
}
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<ul class="mt-4">
<div v-for="review in prime.allReviews" :key="review">
<li v-for="pro in limitedPros(review)" :key="pro">
{{ pro }}
</li>
</div>
</ul>
</div>

List rendering in vue

I'm running through a list of cart items in vue and need to get the index of each item. I thought you'd simply do something like this
<ul class="crt-Push_Items">
<li class="crt-Push_Item" v-for="(lineItem, index) in lineItems" :key="lineItem.key">
<PushCartItem :lineItem="lineItem" />
</li>
</ul>
And
<p class="crt-PushItem_Price"><span class="money" data-line-index="{{ index }}">{{ formatMoney(lineItem.line_price) }} </span></p>
But this isn't displaying and I'm getting the error
[Vue warn]: Property or method "index" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
I'm assuming that this line
<p class="crt-PushItem_Price"><span class="money" data-line-index="{{ index }}">{{ formatMoney(lineItem.line_price) }} </span></p>
is the PushCartItem component, so in order to receive the index property, you need to use props, because otherwise you can't have access to it, like this:
<template>
<p class="crt-PushItem_Price">
<span class="money" :data-line-index="index">
{{ formatMoney(lineItem.line_price) }}
</span>
</p>
</template>
<script>
export default {
name: 'PushCartItem',
props: {
index: {
type: Number,
required: true
},
lineItem: {
type: Object,
required: true,
}
},
methods: {
formatMoney(price) {
// do something with the price
}
}
}
</script>
This answer is based in my assumptions, if you still having the error, please give me more information or details about it to help you.
You need to pass the index from the parent component like this.
<ul class="crt-Push_Items">
<li class="crt-Push_Item" v-for="(lineItem, index) in lineItems" :key="lineItem.key">
<PushCartItem :lineItem="lineItem" :index="index" />
</li></ul>
Try this:
<ul class="crt-Push_Items">
<li class="crt-Push_Item" v-for="(lineItem) in lineItems" :key="lineItem.key">
<PushCartItem :lineItem="lineItem" />
</li>
</ul>
Or this:
<ul class="crt-Push_Items">
<li class="crt-Push_Item" v-for="(lineItem, index) in lineItems" :key="index">
<PushCartItem :lineItem="lineItem" />
</li>
</ul>

vue-drag-drop: context on target of drop event

This is probably a really naive question that is less about vue-drag-drop and more about vuejs, which I'm new to.
If I have two lists of stuff:
<ul>
<li v-for="thing in thing">
<drag :transfer-data="{ thing }">
<span>{{ thing.title }}</span>
</drag>
</li>
</ul>
<ul>
<li v-for="day in days">
<drop #drop="handleDrop" ref="day"></drop?
</li>
</ul>
In the handleDrop() method I can see the event, which include what was dragged into the list item, but I don't see how I have any context on which item in the array the dragged thing was dragged into. I tried using a ref on the drop element, but that didn't seem to be what I wanted.
How do I know which day the item was dragged into?
I figured out I need to pass the data myself. One way to do this is to wrap the function vue-drag-drop provides.
<ul>
<li v-for="day in days">
<drop #drop="function(data, event) { handleDrop(data, day, event); }" ref="day"></drop>
</li>
</ul>
That seems to work as expected, but I'm wondering if there's another way to do it like using a library attribute (similar to ref).
Maybe I missed something, but wouldn't this in handleDrop() be the component that was dropped onto? That's how it is for other event handlers in Vue.
See here for an example:
<div id="example-2">
<!-- `greet` is the name of a method defined below -->
<button v-on:click="greet">Greet</button>
</div>
var example2 = new Vue({
el: '#example-2',
data: {
name: 'Vue.js'
},
// define methods under the `methods` object
methods: {
greet: function (event) {
// `this` inside methods points to the Vue instance
alert('Hello ' + this.name + '!')
// `event` is the native DOM event
if (event) {
alert(event.target.tagName)
}
}
}
})
// you can invoke methods in JavaScript too
example2.greet() // => 'Hello Vue.js!'
Update
The above is true, but you want to know which day is that drop component. To achieve that, pass it as a prop to the child drop component like so:
Vue.component('drop', {
props: ['day'],
// ...
})
<ul>
<li v-for="day in days">
<drop #drop="handleDrop" ref="day" :day="day"></drop>
</li>
</ul>
The :day="day" is the key. Then, in handleDrop(), this.day will be the day

v-if and v-else inside of v-for for different text rendering

I can't find a way to choose different options for rendering text inside of v-for. Is it possible or do I need to structure the logic differently to do something like the code below?
<template>
<ul v-show="showNotifications">
<li v-for="notification in notifications">
// if notification.type = 'friend request'
New friend request from {{ notification.name }}
// else
New notification from {{ notification.name }}
</li>
</ul>
</template>
Notification is a array of objects with data like name and notification type.
Use another template element like following (not tested)
<template>
<ul v-show="showNotifications">
<li v-for="notification in notifications">
<template v-if="notification.type == 'friend request'">
New friend request from {{ notification.name }}
</template>
<template v-else>
New notification from {{ notification.name }}
</template>
</li>
</ul>
I did what Xymanek said and that isn't work for me completely, I also added a method like this since I realize the component is reactive to the variable in "v-for", in this case "notifications"
forceReload(){
this.files.push(fakeNotification);
this.files.pop();
}
as can see this just force the v-for to "re-render" by pushing a fake object to the array.
you can call this method just after the value of "notification.type" change.

How do I toggle the classes of individual <li> elements?

When I toggle my variable active in the code below, the active CSS class is applied/removed from all elements in the list. How do I target the list elements individually? The Todo-List example has similar functionality (with todo / todo completed), but it's a bit beyond my skill set.
<ul>
<li v-bind:class="{ active: active }" v-on:click="toggleActive">Test 1</li>
<li v-bind:class="{ active: active }" v-on:click="toggleActive">Test 2</li>
<li v-bind:class="{ active: active }" v-on:click="toggleActive">Test 3</li>
</ul>
toggleActive: function() {
this.active = !this.active;
}
One way to do it is to store each state inside an item object. So you would need to create an array of items, and each item would have the structure:
{
text: "item #"
active: true
}
Note I'm passing the item reference when calling the toggleActive method.
<li v-for="item in items"
v-bind:class="{ active: item.active }"
v-on:click="toggleActive(item)">
{{ item.text }}
</li>
toggleActive: function(item) {
item.active = !item.active;
console.log(item);
}
Here a working example: https://jsfiddle.net/pkwroL5L/1/
Hope it help!
If you want to toggle the clasess of individual elements programattically by VueJS
VueJS allows you to bind the class of the anchor tag (e.g) directly to the index of the li element so that when the vuejs variable bound to the index changes, the class also changes. Check these two links for more details
This is the crux of the solution
:class="{current:i == current}
available on the fiddle below and another post that explains in blog format how anchor class can be dynamically controlled in vuejs
https://jsfiddle.net/Herteby/kpkcfcdw/
https://stackoverblow.wordpress.com/2021/04/03/how-modern-javascript-makes-click-simulation/