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
Related
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()
}
}
So I have 2 checkbox inputs for each element in an array. The first represents a field in a form and the second represents the fact that the field is required or not, I need to construct and array of objects like so
[
{
name: 'fieldName',
required: true
},
{
name: 'anotherFieldName'
}
]
If the first checkbox is checked I need to add an object with the "name" property in my array, and if the second one is checked too I also need to add the "required" field.
try this
<li v-for="(item, index) of items">
{{ item.prop2 }}
<input type="text" v-model="items[index].prop2">
</li>
or
<li v-for="(item, index) of items">
{{ item.prop2 }}
<input type="text" #input="updateMyProp(index)">
</li>
...
methods: {
updateMyProp ($event, index) {
// your update logic here
// you can use 'this.items', Object.assign, Vue.set, etc... to update your value
}
...
I'm using php for creating set of computed properties in my app based on ID property of each object in my main array of data stored in property deals. So i have now computed properties like list_10_deals_cnt, list_20_deals_cnt, list_30_deals_cnt etc. Now, how can I create these dynamic created properties in span with class dials__cnt while looping my array of data? {{'list_'+el.id+'_deals_cnt'}} is not working as i wish, its display just a string like list_10_deals_cnt instead to display a computed value.
P.S. sorry about my english.
<div class="dials" id="app">
<div class="dials__column" v-for="(el, index) in deals">
<div class="dials__header">
<div>{{el.title}}</div>
<div>сделок: <span class="dials__cnt">{{`'list_'+el.id+'_deals_cnt'`}}</span>, <span></span> руб</div>
</div>
<draggable drag-class="draggable-ghost__class" class="dials__block" :list="el.items" group="deal" #change="log(el.id, $event)">
<div
class="dials__card"
v-for="(el, index) in el.items"
:key="el.title"
>
<div class="card__header">
<div class="card__title">{{ el.customer_name }}, {{ el.customer_company_name }}</div>
<div class="card__date">{{ el.created_at }}</div>
</div>
<div class="card__body">
<a :href="'/deal/detail/'+el.id" class="card__link">{{ el.title }}</a>
</div>
<div class="card__footer">
<span class="card__price">{{ el.price }} руб </span>
<span v-for="(tag, index) in el.tags" class="card__tag">{{ tag }}</span>
</div>
</div>
</draggable>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
deals: <?php echo json_encode($deals, JSON_UNESCAPED_UNICODE); ?>
},
computed: {
<?php
foreach ($deals as $k=>$v) {
echo 'list_'.$v->id.'_deals_cnt: function() {return this.deals['.$k.'].items.length},';
}
?>
},
methods: {
log: function(id, evt) {
if (evt.hasOwnProperty('added')) {
let dealID = evt.added.element.id;
console.log('сделка ID '+dealID+' перемещена в статус '+id+'. Отправляем аякс запрос на обновление статуса в бд');
// ajax for update
}
}
}
});
</script>
Hi
Problem 1
you will not be able to get the value of computed property by using this
{{`'list_'+el.id+'_deals_cnt'`}}
for the same reason as console.log('vari' + 'able') doesn't print out value of variable to the console.
( Vue evaluates whatever is in between {{ }} as an expression ).
Solution
I suppose, you can either use the deals property directly in html as shown below without using a computed property
<div class="dials__column" v-for="(el, index) in deals">
<div class="dials__header">
<div>{{el.title}}</div>
<div>сделок: <span class="dials__cnt">{{ el.items.length }}</span>, <span></span> руб</div>
</div>
----------- rest of the code
or you can create a computed property based on deals data property and use that to loop in html using v-for.
Problem 2
I don't think below code is valid php string. although it becomes irrelevant if you use first solution above.
<?php
foreach ($deals as $k=>$v) {
echo 'list_'.$v->id.'_deals_cnt: function() {return this.deals['.$k.'].items.length},';
}
?>
the ' inside ['.$k.'] should be escaped.
Solution
echo 'list_'.$v->id.'_deals_cnt: function() {return this.deals[\'.$k.\'].items.length},';
I am creating a list of check boxes via a result set. I can see the correct values but I am not able to set the value correctly
<ul>
<li v-for="role in roles">
<input type="checkbox" :value="role.id" v-model="form.roleIds" > {{role.name}}
</li>
</ul>
When I click on one of the check boxes, I see all of them clicked.
That's what I see in console:
I think your data property roleIds is not defined properly, it should be like this -
roleIds: []
Test.vue
<template>
<ul>
<li v-for="(role, i) in roles" :key="i">
<label>
<input type="checkbox" :value="role.id" v-model="form.roleIds" >
{{role.name}}
</label>
</li>
</ul>
</template>
<script>
export default {
data: () => ({
form: {
roleIds: [] // **this is the catch**
},
roles: [{
id: 1,
name: 'Siddharth'
},
{
id: 2,
name: 'Arora'
}]
})
}
</script>
Console the roles array and confirm there is value for id in every entries of roles. It seems like the value for id is null.
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
},