For loop of objects - vue.js

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
},

Related

Can't display datetime from v-for

I'm trying to show the datatime in a v-for, but it just keeps showing the same time over and over.
Is there a way to do this?
v-for -
<div class="location-box-container">
<ul class="location-box-list">
<ol v-for="(location, index) in lineStringData" :key="lineStringData.id">
<p class="locations">{{ location_time }} New Location</p>
</ol>
</ul>
</div>
JS -
data() {
return {
location_time: new Date().toLocaleTimeString(),
}
},
Use a method to lookup time. Not sure where you are storing the time, but you can look up timezone from coords if needed.
<div class="location-box-container">
<ul class="location-box-list">
<ol v-for="(location, index) in lineStringData" :key="lineStringData.id">
<p class="locations">{{ getTime(location) }} New Location</p>
</ol>
</ul>
</div>
methods: {
getTime(location) {
// lookup your timezone, etc here.
return new Date(location.theTime).toLocaleTimeString()
}
}

Vue.js - How to display all property keys and nested property values?

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>

VUEJS V-FOR acting weird

I need a simple v-for to render object properties in a list.
<div
v-if="profileData && profileData.length > 0"
>
<ul
v-for="value in profileData"
:key="value.id"
>
<li>{{value.id}}</li>
</ul>
</div>
In the script:
profileData: {},
created() {
const userId = this.$route.params.userId
const currentUser = this.$store.getters.currentUser
const profileData = this.$store.getters.profileData
console.log('profileData in seeProfile: ', profileData) }
(profileData comes from an api response)
I did exactly the same in two other pages (just rendering different objects) and it worked.
With this code, in the console I get value is undefined.
If I remove :key="value.id" (it becomes red in the editor but it still works), and instead of the list items I type only {{ value }}}, then the object properties get rendered ( but in the ugly format of a js object). How can it be? What am I doing wrong?
Thank you
Your v-if will never show even if profileData has data, because you can't directly check for the length of an Object in javascript.
A few things:
You can't check for the length of an Object, it will return undefined. If you must use an object, then you'd have to check for Object.keys(obj).length.
let obj = {
first: {
name: "first",
meta: "data"
},
second: {
name: "second",
meta: "data"
}
};
console.log("Object.length is: ", obj.length);
console.log("Object.keys().length is: ", Object.keys(obj).length);
You're being redundant, you don't need to check for profileData and its length (and you don't need to > 0), you could simply check for v-if="Object.keys(profileData).length". If the Object has zero entries, then it won't show because if(0) is false.
I'd strongly recommend to work with arrays to iterate with v-for. I'd use computed properties and return an array, and iterate through that. Object reactivity works non-intuitively in JS, so you'll be scratching your head later when you try to find out why stuff isn't updating on your view:
computed: {
listData() {
let list = Object.values(this.profileData);
return list;
}
}
In view:
<div v-if="listData.length"/>
Also, don't use the array's entry index as your :key, because if you have another array with v-for, you'll have duplicated keys in your model. I'd use something like v-for="(item, key) in list" :key="'list-item-' + key"
Put the v-for on the li, not the ul.
<ul>
<li v-for="value in profileData"
:key="value.id">{{value.id}}</li>
</ul>
Also , if your your profileData is an object and not an array, you need to decide if you want to loop through the keys or values.
<ul>
<li v-for="value in Object.values(profileData)"
:key="value.id">{{value.id}}</li>
</ul>
<ul>
<li v-for="value in Object.keys(profileData)"
:key="value.id">{{value.id}}</li>
</ul>
Or use Vue's default behavior.
<ul>
<li v-for="(value,key) in profileData"
:key="value.id">{{value.id}}</li>
</ul>
The api has been changed, so the working code is slightly different from the original one.
Here's the template:
<div
v-if="listData.length"
>
<ul>
<li>Name: <b>{{ profileData.user.first_name }}</b></li>
<li>Surname: <b>{{ profileData.user.last_name }}</b></li>
<li>Username: <b>{{ profileData.user.username }}</b></li>
<li>Car: <b>{{ profileData.if_cars_owned }}</b></li>
<li v-if="profileData.if_cars_owned === true">
Car model: {{ profileData.user_car_type }}
</li>
<li v-if="profileData.if_cars_owned === true">
Car power: {{ profileData.user_car_powered_by }}
</li>
<li>Motorcycle: <b>{{ profileData.if_motorcycle_owned }}</b></li>
<li v-if="profileData.if_motorcycle_owned === true">
Motorcycle model: {{ profileData.user_motorcycle_characteristic }}
</li>
</ul>
</div>
Script:
created(){
const profileData = this.$store.getters.profileData
this.profileData = profileData
console.log('profile data in profilo: ', profileData)
},
I've also updated
<div
v-if="listData.length"
>
and in the script
computed: {
...,
listData() {
let list = Object.values(this.profileData);
return list;
}
},
following the advice of #Adrián S. Basave.
Thanks to anyone who tried to help.
x

Printing key in Vue.js iteration

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>

How can I switch the `selected` style easily in Vue?

How can I switch the selected style easily?
In the template I have a nav:
<ul class="nav">
<li class="nav-item selected" #click="clickLi(0)"><router-link to="/">首页</router-link></li>
<li class="nav-item" #click="clickLi(1)"><router-link to="/data-center">数据中心</router-link></li>
</ul>
in the methods:
clickLi(page_num){
// there I have to clear all the li `selected` style, then add the style to the page_num.
}
in Vue whether there is a better way to realize this effect?
Take a look at Cass and Style Binding Docs
pseudo example below, also added some shorcuts to vue-router to avoid the router-link component, you just can bind the :to to the <li>
<li
v-for="(item, $index) in routes"
#click="selectedIndex = $index"
:class="{'item-selected': $index == selectedIndex}"
:to="item.path">{{ item.name }}</li>
// on component
data() {
return {
selectedIndex: null,
routes: [{path:'/', name: 'home'},{path:'/data-center', name:'data center'}]
}
}
in the data you return a selected_num param:
data() {
return {
selected_num: 0
}
}
in your template:
<ul class="nav">
<li class="nav-item" :class="selected_num===0 ? 'selected' : ''" #click="selected_num=0"><router-link to="/">首页</router-link></li>
<li class="nav-item" :class="selected_num===1 ? 'selected' : ''" #click="selected_num=1"><router-link to="/data-center">数据中心</router-link></li>
</ul>
you even do not need the method.