Nested v-for loops in a vue-components - vue.js

I'm trying to use a vue.js component to display the following data (in a vue instance) as a table.
But I not sure how to access the data. I tried nested v-for loops.
OUTPUT TABLE
Equp Name | Service Time
Mill Saw | 2018-02-01 10:00:00
Mill Saw | 2018-02-04 10:00:00
Equp Name | Service Time
Jack Hammer | 2018-02-06 12:30:00
VUE COMPONENT
Vue.component('services', {
props: ['value'],
template: '<div>{{value.serviceTime}}</div>'
})
new Vue({
el: '#mydemo1',
data: {
"results": {
"4": [
{
"service": 4,
"serviceTime": "2018-02-01 10:00:00",
"usrname": "chris job",
"eqname": "mill saw",
"quantity": "3.00",
"rate": "20.00",
"total": "60.00",
"note": ""
},
{
"service": 4,
"serviceTime": "2018-02-04 10:00:00",
"usrname": "chris job",
"eqname": "mill saw",
"quantity": "3.00",
"rate": "20.00",
"total": "0.00",
"note": null
}
],
"34": [
{
"service": 34,
"serviceTime": "2018-02-06 12:30:00",
"usrname": "chris job",
"eqname": "jack hammer",
"quantity": "0.00",
"rate": "20.00",
"total": "0.00",
"note": "Training"
}
]
HTML
div id="mydemo1">
<services v-for="invoice in results"
v-for="items in invoice"
v-for="details in items"
v-bind:value="invoice"
></services>
Suggestions?

You can do
<table v-for="(invoices, key) in results" :key="key">
<tr>
<th>Equp Name</th>
<th>Service Time</th>
</tr>
<tr v-for="item in invoices" :key="item.serviceTime">
<td>{{ item.eqname }}</td>
<td>{{ item.serviceTime }}</td>
</tr>
</table>
You can check my demo at https://codepen.io/ittus/pen/erMRNL

You should do it in this fashion
<div id="mydemo1">
<services v-for="invoice in results"
v-for="items in invoice">
<div v-for="details in items">Do your stuff ....</div>
</services>
</div>

Yes you can nest v-for loops but you have to put them inside different elements (as div for example)
Btw, you don't need 3 v-for loops to display you data the way you want :
Vue.component('services', {
template: '<div style="display:inline">{{value.serviceTime}}</div>',
props: ['value']
})
new Vue({
el: '#app',
data: {
"results": {
"4": [
{
"service": 4,
"serviceTime": "2018-02-01 10:00:00",
"usrname": "chris job",
"eqname": "mill saw",
"quantity": "3.00",
"rate": "20.00",
"total": "60.00",
"note": ""
},
{
"service": 4,
"serviceTime": "2018-02-04 10:00:00",
"usrname": "chris job",
"eqname": "mill saw",
"quantity": "3.00",
"rate": "20.00",
"total": "0.00",
"note": null
}
],
"34": [
{
"service": 34,
"serviceTime": "2018-02-06 12:30:00",
"usrname": "chris job",
"eqname": "jack hammer",
"quantity": "0.00",
"rate": "20.00",
"total": "0.00",
"note": "Training"
}
]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<div v-for="invoice in results">
<div v-for="items in invoice">
<div style="display:inline">{{ items.eqname }} |</div>
<services :value="items"></services>
</div>
</div>
</div>
Example here with a table

Related

Why is v-for can't show the value with computed

This is for select a city and area, It will filter the same data to show it. But I meet with a problem is that when I selected, the value doesn't appear.
I have been try and searched similar code but still doesn't find the solution.
This is the image when of HTML rendering :
Here is template :
<a href="#" class="list-group-item" v-for="(live , idx) of filterLivingNames" :key="idx">
<h3 class="text-center">{{live.Name}}</h3>
<p>Address:</p>
<p>Phone:</p>
</a>
Here is script
import LivingData from '#/assets/LivingData.json';
export default {
computed: {
livedata(){
return LivingData;
},
filterLivingNames(){
let livelength = this.livedata.length
for(let i = 0 ; i < livelength ; i++){
if(this.livedata[i].Region === this.city && this.livedata[i].Town === this.area){
console.log(this.livedata[i])
return this.livedata[i]
}
else{
continue
}
}
}
}
}
Update json file
[
{
"Id": "1",
"Name": "Hotel-1",
"Region": "Region-1",
"Town": "Town-1",
},
{
"Id": "2",
"Name": "Hotel-2",
"Region": "Region-2",
"Town": "Town-2",
},
{
"Id": "3",
"Name": "Hotel-3",
"Region": "Region-2",
"Town": "Town-1",
},
{
"Id": "4",
"Name": "Hotel-4",
"Region": "Region-1",
"Town": "Town-2",
},
]
As you are filtering out the livedata based on Region and Town. You can simply use the Array.filter() method and this will resolve the issue you are facing as it will return the array.
Live Demo :
new Vue({
el: '#app',
data: {
livedata: [
{
"Id": "1",
"Name": "Hotel-1",
"Region": "Region-1",
"Town": "Town-1",
},
{
"Id": "2",
"Name": "Hotel-2",
"Region": "Region-2",
"Town": "Town-2",
},
{
"Id": "3",
"Name": "Hotel-3",
"Region": "Region-2",
"Town": "Town-1",
},
{
"Id": "4",
"Name": "Hotel-4",
"Region": "Region-1",
"Town": "Town-2",
}
],
city: 'Region-1',
area: 'Town-1'
},
computed: {
filterLivingNames() {
return this.livedata.filter(obj => obj.Region === this.city && obj.Town === this.area)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<a href="#" class="list-group-item" v-for="(livingData, index) of filterLivingNames" :key="index">
<h3 class="text-center">{{ livingData.Name }}</h3>
<p>Address:</p>
<p>Phone:</p>
</a>
</div>

How to get list of products in a particular category in vue

I have a list of products under a categoryID, how can I get the display the product under each categoryID
This is my category id data :
{
"success": true,
"category": {
"_id": "62566ec30e42d6c5ab370e7c",
"products": [],
"type": "mobile phone",
"__v": 0
}
}
This is the product data with categoryID :
{
"_id": "62567252370e769a8a93a517",
"category": {
"_id": "62566ec30e42d6c5ab370e7c",
"products": [],
"type": "mobile phone",
"__v": 0
},
"title": "galaxy s10",
}
this my html template to display my data
<div>
<div id="app">
<p>{{category.type}}</p>
<ul>
<li
v-for="product in products"
:key="product._id"
>
{{ product.title }}
</li>
</ul>
</div>
</div>
I get the {{ category.type }}, but when looping through the product I get all the products from my database instead of the products in a particular categoryID
How can I display the list of product under {{ category.type }} each time I go to the categoryID route.
Try this :
new Vue({
el: '#app',
data: {
category: {
"_id": "62566ec30e42d6c5ab370e7c",
"products": [],
"type": "mobile phone",
"__v": 0
},
products: [{
"_id": "62567252370e769a8a93a517",
"category": {
"_id": "62566ec30e42d6c5ab370e7c",
"products": [],
"type": "mobile phone",
"__v": 0
},
"title": "galaxy s10"
}, {
"_id": "62567252370e769a8a93a517",
"category": {
"_id": "62566ec30e42d6c5ab370e7c",
"products": [],
"type": "mobile phone",
"__v": 0
},
"title": "One Plus"
}]
},
mounted() {
const catID = category._id;
this.products = this.products.filter(({ category }) => catID === category._id);
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p>{{category.type}}</p>
<ul>
<li v-for="product in products" :key="product._id">
{{ product.title }}
</li>
</ul>
</div>

Vue country and state selection with select2

I want to list the states of the country in 2nd selection (JSON) format when country is selected in 1 selection I want to make with vuejs. I can do this with normal select but I want to do it in "select2" action. I have not seen or encountered an example of it anywhere.
For example, when France is chosen as the country. in the second option i want the states of france to be listed
Please answer considering that you are a beginner when writing an answer.
select2 or vue-select
[
{
"country": "America",
"plate": 1
},
{
"country": "France",
"plate": 2
},
{
"country": "Holland",
"plate": 3
},
{
"country": "China",
"plate": 4
},
{
"country": "state",
"plate": 5
}
]
[
{
"id": 1,
"country": "America",
"state": "Texas"
},
{
"id": 2,
"country": "America",
"state": "NewMexico"
},
{
"id": 3,
"country": "America",
"state": "Montana"
},
{
"id": 4,
"country": "France",
"state": "Normandy"
},
{
"id": 5,
"country": "France",
"state": "Paris"
},
{
"id": 6,
"country": "France",
"state": "Occitanie"
},
{
"id": 7,
"country": "Holland",
"state": "Köln"
},
{
"id": 8,
"country": "Holland",
"state": "Brüksel"
},
{
"id": 9,
"country": "China",
"state": "Gansu"
},
{
"id": 10,
"country": "China",
"state": "Hubei"
},
{
"id": 11,
"country": "China",
"state": "Hainan"
},
{
"id": 12,
"country": "Iraq",
"state": "Erbil"
},
{
"id": 13,
"country": "Iraq",
"state": "Bagdat"
}
]
<template>
<div class="container">
<div class="row">
<div class="col-md-4">
<label class="my-1 mr-2">countries</label>
<select class="custom-select my-1 mr-sm-2 form-control" v-model="selected" #change="getState()">
<option v-if="selected === 'Choose'">Choose</option>
<option v-for="item in countries" v-bind:key="item.id">{{ item.country}}
</option>
</select>
</div>
<div class="col-md-4 ">
<label class="my-1 mr-2">state</label>
<select class="custom-select my-1 mr-sm-2 form-control">
<option v-if="selectedCountry === false">Choose</option>
<option v-for="list in states" v-bind:key="id">{{ list.state}}</option>
</select>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
selected: 'Choose',
countries: {},
states: [],
selectedCountry: false,
}
},
created() {
this.getCounty()
},
methods: {
getCounty() {
axios.get('json/country.json')
.then(res => this.countries = res.data)
},
getState() {
this.selectedCountry = true
this.states = []
axios.get('json/states.json')
.then(res => {
res.data.forEach(i => {
if (this.selected === i.country) {
this.states.push(i.state)
}
})
})
}
}
}
</script>
You can prepare data and use vue-multiselect :
Vue.config.productionTip = false
new Vue({
el: '#demo',
components: { Multiselect: window.VueMultiselect.default },
data() {
return {
options: [
{"id": 1,"country": "America", "plate": 1}, {"id": 2,"country": "France","plate": 2},
{"id": 3,"country": "Holland","plate": 3}, {"id": 4,"country": "China","plate": 4},
{"id": 5,"country": "state","plate": 5}
],
states: [
{"id": 1,"country": "America","state": "Texas"},
{"id": 2,"country": "America","state": "NewMexico"},
{"id": 3,"country": "America","state": "Montana"},
{"id": 4,"country": "France","state": "Normandy"},
{"id": 5,"country": "France","state": "Paris"},
{"id": 6,"country": "France", "state": "Occitanie" },
{"id": 7,"country": "Holland","state": "Köln"},
{"id": 8,"country": "Holland","state": "Brüksel"},
{"id": 9,"country": "China","state": "Gansu"},
{"id": 10,"country": "China","state": "Hubei"},
{"id": 11,"country": "China","state": "Hainan"},
{"id": 12,"country": "Iraq","state": "Erbil"},
{"id": 13,"country": "Iraq","state": "Bagdat"}
],
value: '',
statesSel: [],
selectedCountry: '',
}
},
methods: {
getCounty() {
//axios.get('json/country.json')
//.then(res => this.countries = res.data)
},
getStates() {
//axios.get('json/states.json')
//.then(res => {this.states.push(i.state)
},
updateSelected: function(newValue) {
this.selectedCountry = '';
this.statesSel = this.states.filter(s => s.country === newValue.country)
}
},
created() {
this.getCounty()
this.getStates()
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect#2.1.0/dist/vue-multiselect.min.css">
<script src="https://unpkg.com/vue-multiselect#2.1.0"></script>
<div id="demo">
<div class="row">
<div class="col-md-4 col-md-ofset-2 form-group">
<label class="typo__label">Select with search</label>
<multiselect v-model="value" placeholder="İl" :multiple="false" :options="options" label="country" track-by="country" :allow-empty="false" #select="updateSelected">
</multiselect>
</div>
<div class="col-md-4 col-md-ofset-2 form-group">
<label class="typo__label">Select with search</label>
<multiselect v-model="selectedCountry" placeholder="İlçe" :multiple="false" :options="statesSel" label="state" track-by="state" :allow-empty="false">
</multiselect>
</div>
</div>
</div>

DataTable reorder data automatically in Vuetify v0.12

Project features:
- VueJS
- Vuetify v0.12
I have an Object Json that I get from the backend already ordered, only to show it in a table. However, v-data-table automatically reorders the JSON and does not show the order I want.
This is my code in my component Table:
<v-data-table :headers="headers" :items="items" :loading="loading" class="elevation-1" hide-actions>
<template slot="headers" scope="props">
<span v-if="props.item.value!='actions'">
{{ props.item.text }}
</span>
</template>
<template slot="items" scope="props">
<td>
<span>props.item.value</span>
</td>
<td>
<v-btn floating small class="green darken-2 mt-0" #click.native="onEdit(props.item)">
<v-icon light>edit</v-icon>
</v-btn>
</td>
</template>
</v-data-table>
export default {
props: ['compName', 'headers', 'items', 'pageCount',
'recordCount', 'loading', 'paginationOpts', 'applyFilters',
'onAdd', 'onEdit', 'onDelete', 'getAmountPerClient'],
methods: {
[...]
},
mounted() {
},
data() {
return {
expanded: false,
pagination: {},
gridRowsPerPageItems: process.env.GRIDS_ROWS_PER_PAGE_ITEMS,
collapsibleFields: {},
}
}
}
My items parameter has a value similar to the following::
[
{
"id": "93d22f3b-8af8-4920-a828-121ecc0e8abe",
"name": "Christhian",
"is_default": false,
"description": null,
"reference_code": null
},
{
"id": "167f32c7-0d84-4ec8-b5a4-fffbb42e293f",
"name": "Client 2",
"is_default": false,
"description": null,
"reference_code": null
},
{
"id": "0ee8f89b-aa5f-45f2-8cfd-5acc94171eba",
"name": "Client Test",
"is_default": false,
"description": null,
"reference_code": null
},
{
"id": "06e79101-8808-49d4-8b4e-41ec6120ed18",
"name": "DEFAULT",
"is_default": false,
"description": null,
"reference_code": null
}
]
But in table, this data has been reorded and show in this other order:
[
{
"id": "06e79101-8808-49d4-8b4e-41ec6120ed18",
"name": "DEFAULT",
"is_default": false,
"description": null,
"reference_code": null
},
{
"id": "0ee8f89b-aa5f-45f2-8cfd-5acc94171eba",
"name": "Client Test",
"is_default": false,
"description": null,
"reference_code": null
},
{
"id": "167f32c7-0d84-4ec8-b5a4-fffbb42e293f",
"name": "Client 2",
"is_default": false,
"description": null,
"reference_code": null
},
{
"id": "93d22f3b-8af8-4920-a828-121ecc0e8abe",
"name": "Christhian",
"is_default": false,
"description": null,
"reference_code": null
}
]
I do not know why it is automatically reordered. I do not have a sort method. The sort is done before the data reaches the datatable.
You can just use the disable-initial-sort directive.
<v-data-table disable-initial-sort ... >

Vue js component with nested data

This is driving me crazy, I have nested data in an array and have not been successful in getting it to render using components, I am able to render it without a component though.
var data2 = {
"team": [{
"id":0,
"author": "Johnnie Walker",
"title": "Aging Your Own Whisky",
"content": "A bunch of steps and a whole lot of content",
"members": [
{
"id": "0",
"name": "name 1",
"text": "bio"
},
{
"id": "1",
"name": "name 2",
"text": "bio"
}
]
},
{
"id":1,
"author": "Captain Morgan",
"title": "Rum stories",
"content": "A bunch of steps and a whole lot of contentttt",
"members": [
{
"id": "3",
"name": "name 3",
"text": "bio"
}
]
}
]}
What I am trying to do is loop through members, here is my current code
index.html
<div id="app2">
<entry v-for="t in team" v-bind:cat="t" v-bind:key="t.id">
<detail v-for="mem in t.members" v-bind:ember="mem" v-bind:key="mem.id"></detail>
</entry>
</div>
and here is my js file
Vue.component('entry', {
props:['cat'],
template: '<div>{{cat.author}}</div>'
})
Vue.component('detail', {
props:['ember'],
template: '<div>{{ember.id}}</div>',
})
var vm2 = new Vue({
el: '#app2',
data: function() {
console.log(data2.team)
return data2;
}
});
The data in entry renders but nothing happens with detail, no warnings either, how do I proceed?
Note: When I approach it this way it DOES work, but this is not using a component:
var vm = new Vue({
el: '#app',
data: function() {
console.log(data2.team)
return data2;
}
});
and the html
<div id="app">
<div v-for="t in team" v-bind:key="t.id" v-bind:author="t.author">
{{t.author}}
<div v-for="m in t.members" v-bind:key="m.id">
{{m.name}}
</div>
</div>
</div>
You either need to add the detail component to the entry template, or you need to add a slot to the entry component.
Here is your code modified to use a slot.
console.clear()
var data2 = {
"team": [{
"id": 0,
"author": "Johnnie Walker",
"title": "Aging Your Own Whisky",
"content": "A bunch of steps and a whole lot of content",
"members": [{
"id": "0",
"name": "name 1",
"text": "bio"
},
{
"id": "1",
"name": "name 2",
"text": "bio"
}
]
},
{
"id": 1,
"author": "Captain Morgan",
"title": "Rum stories",
"content": "A bunch of steps and a whole lot of contentttt",
"members": [{
"id": "3",
"name": "name 3",
"text": "bio"
}]
}
]
}
Vue.component('entry', {
props: ['cat'],
template: '<div>{{cat.author}}<slot/></div>'
})
Vue.component('detail', {
props: ['ember'],
template: '<div>{{ember.id}}</div>',
})
var vm2 = new Vue({
el: '#app2',
data: function() {
console.log(data2.team)
return data2;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app2">
<entry v-for="t in team" v-bind:cat="t" v-bind:key="t.id">
<detail v-for="mem in t.members" v-bind:ember="mem" v-bind:key="mem.id">
</detail>
</entry>
</div>
And here it is modifying the entry component to include the detail.
console.clear()
var data2 = {
"team": [{
"id": 0,
"author": "Johnnie Walker",
"title": "Aging Your Own Whisky",
"content": "A bunch of steps and a whole lot of content",
"members": [{
"id": "0",
"name": "name 1",
"text": "bio"
},
{
"id": "1",
"name": "name 2",
"text": "bio"
}
]
},
{
"id": 1,
"author": "Captain Morgan",
"title": "Rum stories",
"content": "A bunch of steps and a whole lot of contentttt",
"members": [{
"id": "3",
"name": "name 3",
"text": "bio"
}]
}
]
}
Vue.component('detail', {
props: ['ember'],
template: '<div>{{ember.id}}</div>',
})
Vue.component('entry', {
props: ['cat'],
template: `<div>
{{cat.author}}
<detail v-for="mem in cat.members" v-bind:ember="mem" v-bind:key="mem.id">
</detail>
</div>`
})
var vm2 = new Vue({
el: '#app2',
data: function() {
return data2;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app2">
<entry v-for="t in team" v-bind:cat="t" v-bind:key="t.id"></entry>
</div>