I'm new to front end development and am experimenting with learning Vue.js. Suppose I have an array
fruits = ["New York", "Chicago", "London"]
and I have a component named FruitPrices which can work like:
<FruitPrices fruit="London"></FruitPrices>
I was wondering would it be possible to use v-if to create multiple components?
Something along the lines of:
<div v-for="item in fruits" : key="item">
<FruitPrices fruit="item"></FruitPrices>
</div>
This code does not work so I was wondering if anyone experienced with Vue can lend me a helping hand!
When going through a loop in Vue Js it is required to have a key. For instance, if you had fruits = [{id:1, name: London}, {id:2, name: New York}] you could have done v-for="item in fruits" :key="item.id"
but because you dont have it the best option is the one below:
<div v-for="(item, index) in fruits" :key="index">
<FruitPrices fruit="item"></FruitPrices>
</div>
Vue js is going to consider index as the position of each item in the array
here is your component:
<template>
<div>
<div v-for="item in fruits" :key="item">
<FruitPrices :fruit="item"></FruitPrices>
</div>
</div>
</template>
<script>
import FruitPrices from "../somePlace/FruitPrices";
export default {
components: { FruitPrices },
data: () => ({ fruits: ["New York", "Chicago", "London"] })
}
</script>
In this line <FruitPrices fruit="item"></FruitPrices> you must use : before the fruit prop, because you are not passing a string, but a kind of variable,
<FruitPrices :fruit="item"></FruitPrices>
And you are ready to show the fruit's price in each city!
By the way, related to your question about v-if, using v-if with v-for is not a good way to filter, the best way to do it is using computed properties.
<FruitPrices fruit:"item" v-for="(item,index) in fruits" :key="index">
</FruitPrices>
you can use v-for in component tag
Related
I have this simple component that has a person with values that it should display:
TestFor.vue:
<template>
<div v-for = "(value, key) in this.person">
{{key}} : {{value}}
</div>
</template>
<script scoped>
export default {
props: {
person: {
firstName: 'Bob',
lastNmae: 'Andersen',
age: 27
}
}
}
</script>
However I get the Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key error. Which shouldn't occur, because according to documentation: https://v2.vuejs.org/v2/guide/list.html my syntax is valid:
This video tutorial also uses this syntax and it works fine for them. Why doesn't it work for me?
EDIT:
As people have said the require-v-for-key rule is a culprit. Is there any reason behind that rule or is it OK to just disable it?
I've added "vue/require-v-for-key": "off" to package.json and the original code seems to be working now. Am I good or should I enable that rule back? It just seems like an annoyance for no reason.
You need to define key per element of your list. in your case, it's quite trivial:
<div v-for = "(value, key) in this.person" :key='key'>
{{key}} : {{value}}
</div>
Without the key, Vue is unable to link data to components created with v-for. Lack of key means that any modification of the object you iterated would destroy and recreate all the child components, which would bring a number of undesired side effects. Once the key is defined, when collection changes, vue will calculate key for each element, compare it with keys of existing children and act accordingly.
The error is coming from your linter rule: require-v-for-key
You can fix it, with adding the key binding:
<div v-for = "(value, key) in this.person" :key="key">
{{key}} : {{value}}
</div>
The error means you need to bind the key property at your div.
<template>
<div v-for = "(value, key) in person" :key="key">
{{key}} : {{value}}
</div>
</template>
<script scoped>
export default {
props: {
person : {
type : Object,
default : function(){
return {
firstName: 'Bob',
lastNmae: 'Andersen',
age: 27
}
}
}
}
}
}
</script>
I want my array data to be shown in the list, but I'm seeing the following error:
error: Elements in iteration expect to have 'v-bind:key' directives (vue/require-v-for-key) at src\components\Kubismyk.vue:5:9:
My component:
<template>
<div>
<h1>{{ title }}</h1>
<ul>
<li v-for="ninja in ninjas">{{ ninja }}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
title:'hello world',
ninjas: ['yoshi','mario','ryu']
}
}
}
</script>
You need to bind a v-key when using v-for:
<ul v-for="ninja in ninjas" v-bind:key="ninja.id">
<li>{{ ninja.name }}
</ul>```
You need a unique key for v-key when using v-for loops so that Vue can track each node's identity. You could use index in this case:
<li v-for="(ninja, index) in ninjas" :key="index">
You can discover more information about this linter rule in vue/require-v-for-key docs.
I have a JS array formatted similar to
[{type:'text', data: 'some text'},{type: 'image', data: 'link/to/image'}]
for the different values of type I have different vue components (<text-block>, <image-block>) and I want to use a v-for to loop over this array and based on the type, create the right vue component.
The examples for v-for show creating the same element many times like many <li>. Is there a way I can create different elements in a v-for?
You can just use v-if:
<div v-for="(loop, index) in loops" :key="index">
<text-block v-if="loop.type === 'text'"></text-block>
<image-block v-if="loop.type === 'image'"></image-block>
</div>
You can also use dynamic components:
<div v-for="(loop, index) in loops" :key="index">
<component :is="loop.type + '-block'"></component>
</div>
Make sure you have imported the components and defined them on the instance.
You can do something like this, say there's list of movies in an array:
<div id="app">
<ul>
<li v-for="movie in movies">{{ movie }}</li>
</ul>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
movie: ['some movie 1', 'movie 2', 'idk movies man']
}
});
setTimeout(function() {
app.movies.push('random movie');
}, 2000);
</script>
I've got a v-for loop and I would like to access the dynamically created item outside of loop. Is it possible?
<li v-for="item in cart.items">
<h1>{{ item.product.name }}</h1>
</li>
<p>{{ access item.product.name outside }}</p>
data () {
return {
cart: {
items: []
},
products: [
{
name: "name"
},
{
name: "name2"
}
]
}
}
I would like to access all the items so I can display the quantity of
them all.
That is a data operation, not a DOM operation. You don't get your data from the DOM. It is in your viewmodel. As you figured out (and noted in your comment), you can make a computed.
You need to get access from the parent. You can put the v-for on a template tag, and do your iteration there.
<template v-for="item in cart.items">
<li >
<h1>{{ item.product.name }}</h1>
</li>
<p>{{ item.product.name }}</p>
</template>
This allows you access to each item. See: Templates and v-for
I am trying to render a list of objects from my Vue-Instance. Each object should use a component, so I put the component into the v-for-loop. But all I get is list.title and list.text instead of the correct values.
Is there a special way to use components in v-for-loops?
I found this thread in the Vue-Forum, but don't know how to use it or if it's the right way.
App:
<div id="app">
<div v-for="list in lists">
<listcard title="list.title" text="list.text"></listcard>
</div>
</div>
Template:
<template id="listcard-template">
<div class="card">
<h2>{{ title }}</h2>
<p>{{ text }}</p>
</div>
</template>
My component:
Vue.component('listcard', {
template: '#listcard-template',
props: ['title', 'text']
})
Vue-Instance:
new Vue({
el: "#app",
data: {
lists: [
{title: "title1", text: "text1"},
{title: "title2", text: "text2"},
...
]
}
})
Thanks!
You should pass then as dynamic prop using : in front of parameters:
<listcard :title=list.title :text=list.text></listcard>
From documentation:
A common mistake beginners tend to make is attempting to pass down a number using the literal syntax:
<!-- this passes down a plain string "1" -->
<comp some-prop="1"></comp>
However, since this is a literal prop, its value is passed down as a plain string "1", instead of an actual number. If we want to pass down an actual JavaScript number, we need to use the dynamic syntax to make its value be evaluated as a JavaScript expression:
<!-- this passes down an actual number -->
<comp :some-prop="1"></comp>
https://vuejs.org/guide/components.html#Literal-vs-Dynamic