Get all the data from an Array - vue.js

I have an API which was developed using Laravel and i am trying to pass the data into vue js to display it.
The data is like this
electData: Object
category: Array[3]
0: Object
cat_desc: modified
category_id: 95
cost: 56
kwh_used: 99
1: Object
cat_desc: modified
category_id: 95
cost: 56
kwh_used: 99
2: Object
cat_desc: modified
category_id: 95
cost: 56
kwh_used: 99
And i tried to render it by using v-for
<tr>
<td class="clickOption" #click="first">{{ (electCats.category[0].cat_desc) }}</td>
<td>{{ electCats.category[0].kwh_used }}</td>
<td>£{{ electCats.category[0].cost }}</td>
</tr>
The above code display the first object in the array.
My question is that how do i get the 2nd, 3rd etc in the array because when i do this
<tr>
<td class="clickOption" #click="second">{{ (electCats.category[1].cat_desc) }}</td>
<td>{{ electCats.category[1].kwh_used }}</td>
<td>£{{ electCats.category[1].cost }}</td>
</tr>
I get error [Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'cat_desc')"
How can i avoid this error?

[Vue warn]: Error in render: "TypeError: Cannot read properties of
undefined (reading 'cat_desc')"
As per the error, It seems you are trying to access an object from category array which is not available.
Working Demo :
const app = new Vue({
el: '#app',
data() {
return {
electData: {
category: [{
cat_desc: 'Description 1',
category_id: 1,
cost: 51,
kwh_used: 97
}, {
cat_desc: 'Description 2',
category_id: 2,
cost: 52,
kwh_used: 98
}, {
cat_desc: 'Description 3',
category_id: 3,
cost: 53,
kwh_used: 99
}]
},
filteredData: []
}
},
methods: {
getCategoryDetails(categoryId) {
this.filteredData = this.electData.category.filter((obj) => obj.category_id === categoryId)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button v-for="category in electData.category" :key="category.category_id" style="border: 1px solid black" #click="getCategoryDetails(category.category_id)">
{{ category.category_id }}
</button>
<table>
<tr v-for="category in filteredData" :key="category.category_id">
<td>{{ (category.cat_desc) }}</td>
<td>{{ category.kwh_used }}</td>
<td>£{{ category.cost }}</td>
</tr>
</table>
</div>

I would v-for on the <tr> element, something like:
<tr v-for "(category, index) in electCats.category" :key="index" >
<td class="clickOption" #click="categoryClick(index)">{{ (category.cat_desc) }}</td>
<td>{{ category.kwh_used }}</td>
<td>£{{ category.cost }}</td>
</tr>
Where categoryClick() is the function induced by clicking a row. You probably want to pass a parameter into the #click-induced function, perhaps the index, so that the function knows which element you have clicked on.

Related

[Vue warn]: Error in render: "TypeError: Cannot read property '"' of undefined"

i am getting some warning message.The data is displaying fine.How can i resolve the warning.
Warning: vue.runtime TypeError: Cannot read property 'users' of undefined
<tbody>
<tr v-for= "(item,index) in data.profile.users" :key="index" >
<template v-for="(date,user,i) in item">
<td>
{{user}}
</td>
<td>
{{ date }}
</td >
</template>
</tr>
</tbody>
export default {
props:['data'],
},
It would be helpful if you could provide what the error message was. Just from looking at your code the issue could be:
The extra quote here
<td">
Seems like your profile data isn't resolved yet. You can resolve it in a computed property and thane cast it values. Also notice that you can destructure your properties in v-for in order to access it, by default it takes value and index of iterable object.
<tbody>
<tr v-for= "({date, user}, i) in users" :key="i">
<td>
{{user}}
</td>
<td>
{{ date }}
</td>
</tr>
</tbody>
export default {
props:['data'],
computed: {
users() {
return this.data?.profile?.users
}
}
},

vue.js - How to split array of objects and display in two different columns

I have two columns with name and age.The jason returns the following object.I would to return the value under name and age column.
Students: {
details: [
{ John: 21 },
{ Brian: 22 },
{ Ryan: 21 },
<tbody>
<tr v-for= "(item,index) in Students.details" :key="index" >
<td ">
{{item --(should display name)}}
</td>
<td">
{{item --(should display age)}}
</td >
</tr>
</tbody>
This could work out:
<tbody>
<tr v-for= "(item, index) in Students.details" :key="index" >
<td>
{{Object.keys(item)[0]}}
</td>
<td>
{{item[Object.keys(item)[0]]}}
</td >
</tr>
</tbody>
There are many ways to solve your problem, but I suggest to arrange the data first to a simpler form then render them. For example, use computed to change the form first.
computed: {
dataArray() {
return Object.keys(this.Students).map(name => {
return {
name: name,
age: this.Students[name]
}
})
}
}
// you can get an array [{name: "John", age: 21}, {name: "Brian", age: 22}, ...]
Then in the template just show the data:
<tr v-for= "item in dataArray" :key="item.name">
<td>
{{ item.name }}
</td>
<td>
{{ item.age }}
</td >
</tr>

iterating over multiple table rows with v-for

In a Vue app, I want to render multiple table rows for each item in a collection. Currently the (simplified) markup that renders the table body is
<tbody>
<template v-for="item in collection">
<tr>
<td>{{item.foo}}</td>
<td>{{item.bar}}</td>
</tr>
<tr>
<td>{{item.foo2}}</td>
<td>{{item.bar2}}</td>
</tr>
</template>
<tbody>
However, the problem with this is that there's no key defined, if I try to add one with
<template v-for="item in collection" :key="item.id">
Then I get an eslint error informing me that keys are only allowed on real elements. I can't replace <template> with a real element such as
<tbody>
<div v-for="item in collection" :key="item.id">
<tr>
<td>{{item.foo}}</td>
<td>{{item.bar}}</td>
</tr>
<tr>
<td>{{item.foo2}}</td>
<td>{{item.bar2}}</td>
</tr>
</div>
<tbody>
Because the only element that can be nested inside <tbody> is a <tr>. How can I add a key without violating either the HTML nesting rules or eslint rules?
Rather than trying to reshape the template to fit the data, you may be able to reshape the data to fit the template. Here's an example where the collection is split into an array of rows so that a simple v-for can be used with <td> elements:
<template>
<tbody>
<tr v-for="(item, index) in rows" :key="index">
<td>{{ item.column1 }}</td>
<td>{{ item.column2 }}</td>
</tr>
</tbody>
</template>
const ITEMS = [
{ foo: 'a1', bar: 'a2', foo2: 'b1', bar2: 'b2' },
{ foo: 'c1', bar: 'c1', foo2: 'd2', bar2: 'd2' },
];
export default {
data() {
return { items: ITEMS };
},
computed: {
rows() {
const result = [];
this.items.forEach(({ foo, bar, foo2, bar2 }) => {
result.push({ column1: foo, column2: bar });
result.push({ column1: foo2, column2: bar2 });
});
return result;
},
},
};

Vue2 list with filter

I´m trying to make a foreach loop in a table with a input filter in Vue2. This works but i need to create a filter.
The input code is
<div class="form-group">
<input v-model="search" class="form-control" placeholder="Search shortcut...">
</div>
The loop is
<tr v-for="edition in editions" >
<td></td>
<td class="alert alert-success">{{ edicion.intellij }}</td>
<td class="alert alert-info">{{ edicion.eclipse }}</td>
<td>{{ edicion.descripcion }}</td>
</tr>
QUESTION UPDATE
This is js (Vue) code. In this code 'editions' have only one element, but in real case have more than one element.
new Vue({
el: '#app',
data: {
search: '',
editions: [{
intellij: "Ctrl + Espacio",
eclipse: "Ctrl + Espacio",
description: "Autocompletado de código (clases, métodos, variables)"
}],
},
});
Now, ¿how can i make the input text can filter 'editions'?
I'm not 100% sure I know what you're asking, but it sounds like you want to use the text input as a search field that will filter the array.
https://codepen.io/nickforddesign/pen/YYpZYe?editors=1010
As the value of this.search changes, the computed value will filter the array, and if the field is empty, it will just return the array.
<div class="app">
<input type="text" v-model="search">
<table>
<tbody>
<tr v-for="(edition, index) in matches" :key="index">
<td></td>
<td class="alert alert-success">{{ edition.intellij }}</td>
<td class="alert alert-info">{{ edition.eclipse }}</td>
<td>{{ edition.description }}</td>
</tr>
</tbody>
</table>
And the js:
new Vue({
el: '.app',
data() {
return {
search: '',
editions: [{
intellij: "Ctrl + Espacio",
eclipse: "Ctrl + Espacio",
description: "Autocompletado de código (clases, métodos, variables)"
}, {
intellij: "Ctrl + C",
eclipse: "Ctrl + C",
description: "Copiar"
}, {
intellij: "Ctrl + V",
eclipse: "Ctrl + V",
description: "Pegar"
}]
}
},
computed: {
matches() {
return this.search
? this.editions.filter(edition => {
let match = false
for (let key in edition) {
if (edition[key].toLowerCase().includes(this.search.toLowerCase())) {
return true
}
}
})
: this.editions
}
}
})

how to have Vuex mapState with computed properties in vuejs

I'm trying to learn Vuex and tried adding the mapState with local computed property in my Vuejs 2.0 application on top of Laravel 5.4, now while adding so I'm getting following error:
Syntax Error: Unexpected token, expected , (379:32)
377 | },
378 | mapState({
> 379 | contactStore: state => state.contactStore
| ^
380 | })
381 | }
382 | }
Here is my component:
<template>
<div class="row">
<div class="table-responsive">
<table class="table table-striped">
<tbody>
<tr>
<th class="text-left">Contact Name</th>
<th class="text-left">Company Name</th>
<th class="text-left">City</th>
<th class="text-left">Email</th>
<th class="text-left">Mobile</th>
<th class="text-left">Type</th>
<th class="text-left">SubType</th>
<th class="text-left">Profile</th>
</tr>
<tr v-for="(item, index) in tableFilter">
<td class="text-left"><a #click="showModal(item)" data-toggle="modal" data-target="#showContactModal">{{ item.first_name+' '+item.last_name }}</a></td>
<td class="text-left">{{ item.company.name }}</td>
<td class="text-left">{{ item.city }}</td>
<td class="text-left">{{ item.email }}</td>
<td class="text-left">{{ item.mobile }}</td>
<td class="text-left"><span class="badge badge-info">{{ item.company.type }}</span></td>
<td class="text-left"><span class="badge badge-info">{{ item.company.sub_type }}</span></td>
<td class="text-left"><span class="badge badge-info">{{ item.profile }}</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
data(){
return {
id: '',
search: '',
model: []
}
},
computed: {
tableFilter: function () {
const searchTerm = this.search.toLowerCase();
if(this.model)
{
return this.model.filter((item) =>
(item.first_name.toLowerCase().includes(searchTerm)
|| (item.last_name !==null && item.last_name.toLowerCase().includes(searchTerm))
|| (item.company.name !==null && item.company.name.toLowerCase().includes(searchTerm))
);
}
},
mapState({
contactStore: state => state.contactStore
})
}
}
</script>
I'm trying to replace table filter computed property with the current contact_list state, how can I achieve this or I'm doing some mistake, even if I do ...mapState({}) it is showing me same type of error:
Syntax Error: Unexpected token (378:8)
376 | }
377 | },
> 378 | ...mapState({
| ^
379 | contactStore: state => state.contactStore
380 | })
381 | }
what can be done guide me. Thanks
You are getting this error because the babel is not working on your vue file. The laravel-mix library should do this for you, but if you are manually configuring the file using a webpack.config.js file, you will have to attach a babel loader to the vue loader.
I answered this question on another thread... https://stackoverflow.com/a/49581031/1718887