I have array like below
data() {
return {
shoppingItems: [
{name: 'apple', price: '10'},
{name: 'orange', price: '12'}
]
}
}
I am trying to iterate like below
<ul>
<li v-for="item in shoppingItems">
{{ item.name }} - {{ item.price }}
</li>
</ul>
I am getting output like below
apple - 10
orange - 12
But I would like to get output like below
name - apple, price - 10 //I would like to print key dynamically
name - orange, price - 12
You can use (key,value) pair in for loop
var app = new Vue({
el:'#app',
data() {
return {
shoppingItems: [
{name: 'apple', price: '10'},
{name: 'orange', price: '12'}
]
}
}
});
li span{
text-transform: capitalize;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in shoppingItems">
<span v-for="(v,i,count) in item">{{i}} - {{v}}<span v-show="count<(Object.keys(item).length-1)
">, </span></span>
</li>
</ul>
</div>
You can iterate over the keys/values with this :
<div v-for="(value, key) in object">
{{ key }} - {{ value }}
</div>
You can also have the index of the current key :
<div v-for="(value, key, index) in object">
{{ key }} - {{ value }}
// if index > 0, add comma
</div>
Use default way of Vue to do this
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
Easy and simple
Object.Keys(Object) returns an array containing all the key of the object. Now you can use index to fetch the desire key -
<ul>
<li v-for="item in shoppingItems">
{{ Object.keys(item).indexOf(0) }} : {{ item.name }} - {{ Object.keys(item).indexOf(1) }} : {{ item.price }}
</li>
</ul>
Let's assume that we have a person array or list which contain person object persons:
[{name:'Suru', age:4, hairColor:'red'}, {name: 'Sofia', age:'5', hairColor:'green'}]
Now let's loop through person list and get key, value, and index
new Vue({
el: '#app',
data: {
persons: [
{name: 'Suru', age: 4, hairColor: 'red'},
{name: 'Sofia', age: '5', hairColor: 'green'}
]
}
});
<script src="https://unpkg.com/vue"></script>
<div id='app'>
<ul>
<li v-for="person in persons">
<span v-for="(value, key, index) in person">
{{key}}: {{value}} - {{index}}<br>
</span>
<br>
</li>
</ul>
</div>
Related
I am only able to access currentView and subTask, but not subTasks2. Although I'm following the same approach. I want to access the array of objects branches and report in the response. Any hint, please?
[
{
"id": "sss",
"name": "TestDemo",
"visibility": "ss",
"projects": [
{
"name": "ss",
"branchs": [
{
"name": "master",
"state": "none",
"report": {
"branchName": "master",
"projectName": "ss",
"organizationName": "TestDemo",
"failedRuns": 0,
"totalRuns": 0,
"successRunsPercentage": 100
}
}
]
}
]
}
]
Template vuejs (First two binds are working fine). I still want to access branchs and report
<div id="ID1">
<ul>
<li v-for="currentView in responseTest" :key="currentView.id" >
{{ currentView.name }} - {{ currentView.visibility }}
<ul>
<li v-for="subTask in currentView.projects " :key="subTask.id" >
{{ subTask.name }} - {{ subTask.branchs }}
</li>
</ul>
<ul>
<li v-for="subTask2 in subTask.branchs " :key="subTask2.id" >
{{ subTask2.name }} - {{ subTask2.state }}
</li>
</ul>
</li>
</ul>
</div>
The issue you're facing is that subTask is undefined in your third v-for due to incorrect nesting.
You can only access your variables assigned from the v-for inside child components of that element.
The element your subTask2 in subTask.branchs loop needs to be a child of the element that has the subTask variable.
For example:
<div id="ID1">
<ul>
<li v-for="currentView in responseTest" :key="currentView.id">
{{ currentView.name }} - {{ currentView.visibility }}
<ul>
<li v-for="subTask in currentView.projects" :key="subTask.id">
{{ subTask.name }} - {{ subTask.branchs }}
<ul>
<li v-for="subTask2 in subTask.branchs" :key="subTask2.id">
{{ subTask2.name }} - {{ subTask2.state }}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
You may need to play about with the structure and formatting to make it look right but that example should be runnable.
Couldn't find a better title, my issue is hard to describe in one sentence. I'm trying to loop through an imported object generated by some third party package, but its structure is problematic:
obj: {
"name1": {
"property1": "value1",
"property2": "value2",
},
"name2": {
"property1": "value3",
"property2": "value4",
},
"name3": {
"property1": "value5",
"property2": "value6",
}
}
I want to display not just property1 and property2 but also the name preceding these:
- name1
value1
value2
- name2
value3
value4
...
This is the code I have so far:
<ul>
<li v-for="(item, i) in obj" :key="index">
{{ item.property1 }}
<br>
{{ item.property2 }}
</li>
</ul>
How can I display the name as well, given this object' odd structure?
JSFiddle
Just add key property in your v-for loop and render it :
<li v-for="(item,key, i) in obj" :key="index">
{{key}}
<br>
{{ item.property1 }}
<br>
{{ item.property2 }}
</li>
Loop the object key with Object.keys(), and display the object value from the key with another v-for
<script src="https://unpkg.com/vue"></script>
<div id="app">
<ul>
<li v-for="(item, i) in Object.keys(obj)" :key="index">
{{ item }}
<ul>
<li v-for="(property, key) in obj[item]" :key="property">
{{ key }} -> {{ property }}
</li>
</ul>
</li>
</ul>
</div>
I'm trying to do a for loop of a set of objects but since they all aren't named the same, I'm stuck.
<div id="components-demo">
<div>Travel Information</div>
<ul>
<li
v-for="(todo, index) in todos"
v-bind:id="index"
v-bind:title="todo"
>{{todo}}</li>
</ul>
</div>
var newData = #Html.Raw(Json.Encode(Model));
// Object returns like { Passenger: "Tom Jones", Airline: "United Airways", Destination: "Atlanta, GA", etc. }
var vm = new Vue({
el: '#components-demo',
data: {
todos: [
{ newData }
]
}
})
In the developer tools in Vue, it lists out the object fine like:
todos: Array [1]
0: Object
Passenger: "Tom Jones"
Airline: "United Airways"
Destination: "Atlanta, GA"
etc.
At the end I'm looking to list out li's containing these items but can't seem to loop through unless I specify exactly each one.
According to the object you say is constructed.
<div id="components-demo">
<div>Travel Information</div>
<ul>
<li v-for="(item, index) in todos" :key="index">{{ item.Passenger }}</li>
</ul>
</div>
To list out dynamic objects using nested loop:
<div id="components-demo">
<div>Travel Information</div>
<ul>
<li v-for="(item, index) in todos" :key="index">
<ul>
<li v-for="(value, key) in item" :key="key">{{ key }} : {{ value }}</li>
</ul>
</li>
</ul>
</div>
You are assigning the object to an array, you can just loop through the object directly https://jsfiddle.net/cckLd9te/4656/
data: {
todos: newData
},
I have a vue object with an array of items as data (in my case flightplans).
The list is rendered correctly so far.
Now comes the problem. I want to apply different styles while iterating with v-for to each item (flightplan) in the list dependent of the value of current iterated flightplan memeber fplType.
Currently all list items (flightplans) get the class flightplan-list-ifr-dep.
But i need something like (pseudo code):
<li v-for="flightplan in flightplans"
v-bind:id="flightplan.id"
v-bind:class="{
flightplan-list-ifr-dep: flightplan.fplType === 'departure',
flightplan-list-ifr-arr: flightplan.fplType === 'arrival'
}"
>
So each items gets its own class applied dependent from the fplType of the current iterated flightplan.
<div id="flightplan-list-area" class="flightplan-list-area-style">
<ul>
<li v-for="flightplan in flightplans"
v-bind:id="flightplan.id"
#click="selected(flightplan, $event)">
<div class="flightplan-list-ifr-dep">
<p class="flightplan-list-ifr-dep-callsign">{{ flightplan.callsign }}</p>
<p class="flightplan-list-ifr-dep-aircraft-type">{{ flightplan.aircraft_type }}</p>
<p class="flightplan-list-ifr-dep-aircraft-wtc">{{ flightplan.aircraft_wtc }}</p>
</div>
</li>
</ul>
</div>
<script lang="javascript">
var vue_FLIGHTPLAN_MODEL = new Vue({
el: "#flightplan-list-area",
data: {
flightplans: [],
selected_flightplan_element: null,
},
});
</script>
Your syntax is almost right, but since your class names contain the "-" character, you just need to quote them inside v-bind:class:
...
v-bind:class="{
'flightplan-list-ifr-dep': flightplan.fplType === 'departure',
'flightplan-list-ifr-arr': flightplan.fplType === 'arrival'
}"
...
Live demo
var vue_FLIGHTPLAN_MODEL = new Vue({
el: "#flightplan-list-area",
data: {
flightplans: [
{ id: 1, callsign: 'ABC', aircraft_type: 'Boeing 737', aircraft_wtc: 'xyz', fplType: 'departure' },
{ id: 2, callsign: 'DEF', aircraft_type: 'Boeing 737', aircraft_wtc: 'uvw', fplType: 'arrival' },
{ id: 3, callsign: 'HIJ', aircraft_type: 'Boeing 737', aircraft_wtc: 'abc', fplType: 'departure' },
],
selected_flightplan_element: null,
},
methods: {
selected (plan, e) {
this.selected_flightplan_element = plan;
}
},
});
li.flightplan-list-ifr-dep {
color: blue;
}
li.flightplan-list-ifr-arr {
color: green;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="flightplan-list-area" class="flightplan-list-area-style">
<ul>
<li v-for="flightplan in flightplans"
v-bind:id="flightplan.id"
v-bind:class="{
'flightplan-list-ifr-dep': flightplan.fplType === 'departure',
'flightplan-list-ifr-arr': flightplan.fplType === 'arrival'
}"
#click="selected(flightplan, $event)">
<div class="flightplan-list-ifr-dep">
<p class="flightplan-list-ifr-dep-callsign">{{ flightplan.callsign }}</p>
<p class="flightplan-list-ifr-dep-aircraft-type">{{ flightplan.aircraft_type }}</p>
<p class="flightplan-list-ifr-dep-aircraft-wtc">{{ flightplan.aircraft_wtc }}</p>
</div>
</li>
</ul>
</div>
You can either use the object style syntax like so:
<li v-for="flightplan in flightplans">
<div :class="{
'fpl-foo': flightplan.fplType === 1,
'fpl-bar': flightplan.fplType === 2,
'fpl-baz': flightplan.fplType === 3
}">
<!-- ... -->
</div>
</li>
...or use a method:
<li v-for="flightplan in flightplans">
<div :class="getClass(flightplan.fplType)">
<!-- ... -->
</div>
</li>
methods: {
getClass (fplType) {
// Determine the class and return it,
// this can also be an array in case
// of more than one class
}
}
Your pseudocode is right.You can bind a class dynamically.See class and style Bindings
So the follow code will work for you:
<li v-for="flightplan in flightplans"
:key="flightplan.id"
v-bind:id="flightplan.id"
v-bind:class="{
'flightplan-list-ifr-dep': flightplan.fplType === 'departure',
'flightplan-list-ifr-arr': flightplan.fplType === 'arrival'
}"
>
And when using v-for,it is recommended always to use a unique key.
I made a simplify example for you.See it in action
If I have the following data property:
person: {name: 'Joe', age: 35, department: 'IT'}
And wanted to loop through and output it as follows:
name: Joe, age: 35, department: IT
So far I have:
<span v-for="(val, key) in person">{{key}}: {{val}}, </span>
But this displays:
name: Joe, age: 35, department: IT,
with an extra comma on the end, how can I have it detect that it's the last prop and not show the comma? I thoughta v-show or v-if may be the solution but can't quite figure out how to make it work.
Here is one way.
<span v-for="(val,key,index) of person">
key: {{key}}, val: {{val}}, index: {{index}}
<span v-if="index != Object.keys(person).length - 1">, </span>
</span>
Here's a solution if you're looping through an array, rather than an object:
<div id="app">
<div v-for="(item, index) in items">
<div v-if="index == items.length - 1">yes</div>
{{ item }}, {{ index }}
</div>
</div>
You can also "cheat" by inserting the comma before each item, as it's easier to check for the first item (index !== 0).
<span v-for="(val, key, index) in person">
<span v-if="index !== 0">, </span>
{{key}}: {{val}}
</span>
You can do that with a computed to see if the current index (third parameter forv-if) is the last property:
computed: {
last(){
return Object.keys(this.person).length-1;
}
}
Then in your v-for:
<span v-for="(val, key, index) in person">{{key}}: {{val}}<span v-if="index !== last">, </span> </span>
Here's the JSFiddle: https://jsfiddle.net/wv2ujxvn/
This also works:
<span v-for="(value,key) in persons" :key='key'>
{{key}}: {{val}}
<span v-if="key+1 != persons.length">, </span>
</span>
A pity there is no shortcut provided by Vue.
I personally prefer using a small CSS:
<div class="list">
<span>Item 1</span>
<span>Item 2</span>
<span>Item 3</span>
</div>
.list span:not(:last-child)::after {
content: ',';
}
If you want to store the knowledge about this pattern in code instead of on Stack Overflow, you could create a component like this:
<template>
<span v-if="show"><slot></slot></span>
</template>
<script>
export default {
name: 'separator',
props: ['items', 'index'],
computed: {
show () {
return this.index !== (Array.isArray(this.items) ? this.items : Object.keys(this.items)).length - 1
}
}
}
</script>
This doesn't necessarily make the code shorted, but easier to remember:
<span v-for="(val, key, index) of person">key: {{key}}, val: {{val}}
<separator :items="person" :index="index">, </separator>
</span>