VueJS 2: passing a lot of property values to a component - vue.js

What is the best way to pass a lot of property values to a component?
Right now I am doing this:
<list-li
v-for="item in items"
:key="item.id"
:id="item.id"
:user="item.user"
:branch="item.branch"
:title="item.title"
></list-li>
Is there a way to pass one variable containing all the data instead of having to write out :someValue of every data value?
Also, if item.title does not exist, what would happen with :title="item.title"?

You can pass an object to the v-bind directive. Each property of the object will assign that property name and value to the component.
So in your case, you could just pass the item:
<list-li v-for="item in items" :key="item.id" v-bind="item"></list-li>

Related

Vue doesn't rerender list even when using set

I made a list that each item could be removable and my code looked like this:
Template
<template v-for="(timeFrame, index) in form.timeFrames">
<el-form-item >
<el-button #click="removeTimeFrame(index)">
<i class="el-icon-remove"></i>
</el-button>
</el-form-item>
</template>
Js:
removeTimeFrame(index = 0) {
this.$set(this.form, 'timeFrames', this.form.timeFrames.filter((_, i) => index !== i));
}
Somehow the list doesn't rerender until I add an new item to the list. Does anybody know what's wrong with my code?
templates in Vue need a top level element wrapping their content, so you shouldn't assign the v-for directly to the template tag, but instead create a div inside the template tag and either add v-for to the el-form-item component or wrap it in another div-tag.
Additionally, every element in a v-for loop should contain a key. If you do not plan to reorder or delete elements from the loop, the index-value of each element is fine for this. Seeing your example I suspect that a unique identifier, such as a randomly generated unique id, might work better for your use case.

Assign index of v-for to id of created component

I am creating components in a loop in my vue app. However, I need those components to have an id value like "board-1" etc. using the index of the loop. (Just like I did it with v-bind:key="component-${block._uid}".)
How can I achieve this?
<div
class = "col-4"
v-for="(block, index) in layouts"
v-bind:key="`component-${block._uid}`"
>
<Board
id="`board-${block._uid}`"
class="droparea"
#dropped-component="$emit('dropped-component', $event, index)"
:acceptsDrop=true
draggable="true"
>
Layout {{index + 1}}
</Board>
</div>
You need to bind the value for JS code to get executed, otherwise you are attributing a string, not JS code.
:id="`board-${block._uid}`"
You can also use v-bind, actually : is just a shorthand
v-bind:id="`board-${block._uid}`"

How to change value of component property in a code in Vue.js?

I have an array of generic child components in my parent component:
<component v-for="item in items" :key="item.id" :is="componentName">
I can get a child via this.$refs, but I can't set a new value for a prop :is like:
this.$refs[id][0].is = 'MyNewComponentName'
How can I set a value of component instance property in a code?
First define your prop structure like
{
...item, // to use your current variables
componentName: 'MyExistingComponentName'
}
Receive the prop and bind it to a data variable, so something like
data: function() {
returns {
items: this.propItem
}
}
Make the required adjustment in your tag
<component v-for="item in items" :key="item.id" :is="item.componentName">
Now you got 2 options, you can either change the item.componentName by referencing this.items in a method, finding the index and changing it or you could get the parent to change the value of the prop using a custom event using $.event(event-name, 'MyNewComponent`). Both methods are fine, it really depends on your requirements.
Refer to https://v2.vuejs.org/v2/guide/components-custom-events.html
You could also read stackoverflow questions on mutating prop values.

Pass parameter from v-for to dynamically update b-tab title

Only about 6 weeks into using vuejs and haven't looked at components at all, so sorry if this is a dumb question.
I am attempting to make the b-spinner component for tabs from bootstrap-vue update dynamically inside a v-for loop, with the parameter from the v-for being past to a computed property.
It works fine when not in a v-for.
<b-tab>
<template v-slot:title>
<b-spinner type="border" small v-show="!updateDone"></b-spinner> <strong>Tab Title</strong>
</template>
...
</b-tab>
But when I try to pass the player property from the v-for, it breaks. When I try to pass player to the title slot, the entire parent component gets passed.
<b-tab :key="player['player-id']" v-for="player in updatePool">
<template v-slot:title="{player}">
<b-spinner type="border" small v-show="!updateDone(player)"></b-spinner> <strong>{{player['player-name']}}</strong>
</template>
...
</b-tab>
updateDone is a computed property as follows:
updateDone: function (player) {
return _.every(Object.values(this.someObject[player['player-name']]), Boolean)
},
But updateDone is never returned b/c player is an entire Vue object (presumably the parent component)
Hoping for some insight on this.
SOLUTION
Thanks to Antonio
<b-tab v-for="player in updatePickPool" :key="player['player-id']">
<template v-slot:title>
<b-spinner type="border" small v-show="!playerPathComplete(player)"></b-spinner><strong> {{player['player-name']}}</strong>
</template>
...
</b-tab>
According to your comments, I realized that updateDone is a computed property.
Do not use computed property in this case.
You have to use method instead of computed property.
Why?
computed properties are cached and change only when their dependencies change.
In your case, there's no change in player while looping to render tabs. That means it will show the same results of updateDone property. :(
But a method will evaluate every time it's called. :)

Pass for loop item to prop

How do you pass the item instance from the foreach loop as a prop?
<div v-for="n in parentArray">
<blog-card prop="{{ n.content }}"></blog-card>
</div>
When I run this I get an error
(Emitted value instead of an instance of Error)
Can this be done without rebinding the item to the parent component?
With Vue 2 you don't use interpolation in attributes, you use the attribute binding syntax.
<blog-card v-bind:prop="n.content"></blog-card>
Or the shortcut
<blog-card :prop="n.content"></blog-card>