vue - datatable - item-expanded - load from server - vue.js

I'm using the component datatable from Vuetify library. There is a problem on item-expanded, the code
<v-data-table
:headers="headers"
:items="records"
:options.sync="options"
:server-items-length="totalRecords"
:loading="loading"
:search="search"
disable-pagination
:hide-default-footer="true"
class="elevation-1"
show-expand
#item-expanded="loadDetails">
<template v-slot:expanded-item="{ headers, item }">
<td :colspan="headers.length">
<table>
<thead>
<tr>
<th data-field="id" data-visible="false">id</th>
<th data-field="league_id" >league_id</th>
<th data-field="Start" >Start</th>
<th data-field="End" >End</th>
<th data-field="Current" >Current</th>
</tr>
</thead>
<tbody>
<tr v-for="rec in item.details" :key="rec.id">
<td>{{ rec.id }}</td>
<td>{{ rec.league_id }}</td>
<td>{{ rec.start }}</td>
<td>{{ rec.end }}</td>
<td>{{ rec.current }}</td>
</tr>
</tbody>
</table>
</td>
</template>
</v-data-table>
loadDetails: function({item}) {
if (item.details)
return;
this.ChildApiCall(item).then((data) => {
item.details = data.response;
})
// var self = this;
// return new Promise(function (resolve) {
// self.ChildApiCall(item).then((data) => {
// item.details = data.response;
// resolve(item);
// })
// });
},
async ChildApiCall(item) {
let formData = new FormData();
formData.append("action", "GetRecordDetailsLeaguesJS");
formData.append("recID", item.id);
const items = await general.GetData("/api/03leagues.php", formData);
return items;
}
if I add to server call (03leagues.php) 1 second delay on response, the row expanded but showing only the table header row. When collapse and expand again, showing the table as should be.

Related

How to update the value in particular TextBox in Table row using change event in Vue Js

While change the Quantity in the particular TextBox in table row, need to update the calculated Value (Unit Price * Quantity) in another TextBox in the same row.
Template
<template>
<div class="container col-md-12">
<h3>Product List</h3>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Product Name</th>
<th scope="col">Net Content</th>
<th scope="col">MRP</th>
<th scope="col">Discount</th>
<th scope="col">Unit Price</th>
<th scope="col">Quantity</th>
<th scope="col">Value</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<template v-for="group in productgroups">
<tr>
<td colspan="9"><b>{{ group.groupName }}</b></td>
</tr>
<tr v-for="(product, index) in filteredProducts(group.id)" v-bind:key="product.id">
<td class="text-center" scope="row">{{ index + 1 }}</td>
<td>{{ product.productName }}</td>
<td class="text-right">{{ product.netContent }} {{ product.uommasters.uomId }}</td>
<td class="text-right">{{ product.mrp }}</td>
<td class="text-right">{{ product.discountAmount }}</td>
<td class="text-right">
<input type="number" class="form-control" v-bind:id="`salePrice${product.id}`" required name="salePrice" v-model="product.salePrice" readonly />
</td>
<td>
<input type="number" class="form-control" v-bind:id="`quantity${product.id}`" required name="quantity"
#change="getValue(product.id, product.salePrice, product.quantity)" v-model="product.quantity" />
</td>
<td>
<input type="number" class="form-control" :id="'productValue'+product.id" required name="productValue" v-model="product.productValue" readonly />
</td>
</tr>
</template>
</tbody>
</table>
</div>
Script
<script>
import moment from 'moment';
import ProductDataService from "../../services/ProductDataService";
import ProductgroupDataService from "../../services/ProductgroupDataService";
export default {
name: "product-index",
data() {
return {
products: [],
productgroups: [],
productTotal: 0,
};
},
methods: {
getValue(productId, price, qty) {
this.productTotal = price * qty;
alert(this.productTotal);
this.product.discountAmount = this.productTotal;
alert(this.product.discountAmount);
},
filteredProducts(groupId) {
var fproducts = this.products.filter(function(product) {
return product.groupCode == groupId;
});
return fproducts;
},
retreiveProducts() {
ProductDataService.getAll()
.then(response => {
this.products = response.data;
})
.catch(e => {
alert(e);
console.log(e);
})
},
retreiveGroups() {
ProductgroupDataService.getAll()
.then(response => {
this.productgroups = response.data;
})
.catch(e => {
console.log(e);
});
},
},
created() {
this.retreiveProducts();
},
mounted() {
this.retreiveGroups();
},
};
I have populated the products from database using API by grouping and need to update the value while change the quantity using onchange event.

Datatable is not showing data used in vuejs code with api fetching

Need Sample code for vuejs Datatable in html page, getting from api and need to show search box and pagination.
var app = new Vue({
el: '#app',
data: {
search: '',
list: [],
pageSize: 3,
currentPage: 1
},
mounted() {
axios
.get('https://thegreen.studio/ecommerce/E-CommerceAPI/E-CommerceAPI/AI_API_SERVER/Api/Order/GetOrderTestAll.php')
.then(response => (this.list = response.data.body))
},
methods: {
nextPage () {
if ((this.currentPage * this.pageSize) < this.list.length) this.currentPage++;
},
prevPage () {
if (this.currentPage > 1) this.currentPage--;
}
},
computed: {
lists () {
var self = this;
return this.list.filter(function (item1) {
return item1.BuyerName.toLowerCase().indexOf(self.search.toLowerCase()) >= 0
|| item1.BuyerPhoneNo.toLowerCase().indexOf(self.search.toLowerCase()) >= 0
|| item1.BuyerEmail.toLowerCase().indexOf(self.search.toLowerCase()) >= 0
|| item1.BuyerHouseNo.toLowerCase().indexOf(self.search.toLowerCase()) >= 0
|| item1.BuyerState.toLowerCase().indexOf(self.search.toLowerCase()) >= 0
|| item1.OrderPlacedOn.toLowerCase().indexOf(self.search.toLowerCase()) >= 0;
});
}
}
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.18/vue.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/vue#2.1.8/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuejs-paginate/2.1.0/index.js"></script>
<div id="app" class="container" style="width:1000px;margin-left:80px;">
<br />
<br />
<input type="text" class="form-control" v-model="search" placeholder="search" />
<br />
<br />
<table id="tbllist" class="table table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Phone No</th>
<th>Email</th>
<th>House No</th>
<th>Address 1</th>
<th>Address 2</th>
<th>Address 3</th>
<th>Address 4</th>
<th>Address 5</th>
<th>PostCode</th>
<th>City</th>
<th>State</th>
<th>Order Status</th>
<th>Total Price</th>
<th style="width:80px">Order Placed On</th>
</tr>
</thead>
<tbody>
<tr v-for="item in lists">
<td>{{ item.BuyerName }}</td>
<td>{{ item.BuyerPhoneNo }}</td>
<td>{{ item.BuyerEmail }}</td>
<td>{{ item.BuyerHouseNo }}</td>
<td>{{ item.BuyerAddress1 }}</td>
<td>{{ item.BuyerAddress2 }}</td>
<td>{{ item.BuyerAddress3 }}</td>
<td>{{ item.BuyerAddress4 }}</td>
<td>{{ item.BuyerAddress5 }}</td>
<td>{{ item.BuyerPostCode }}</td>
<td>{{ item.BuyerCity }}</td>
<td>{{ item.BuyerState }}</td>
<td>{{ item.OrderStatus }}</td>
<td>{{ item.TotalPrice }}</td>
<td>{{ item.OrderPlacedOn }}</td>
</tr>
</tbody>
</table>
<p>
<button #click="prevPage">Previous</button>
<button #click="nextPage">Next</button>
</p>
page={{currentPage}}
</div>

How to get rid of the Brackets from fetched Nested Array

Good day to you guys.
May I seek your help.
I'm stuck figuring out on how to get rid of the Brackets and Separate each data from my nested array. Here's my code:
<template>
<v-data-table
:headers="headers"
:items="teams"
>
<template v-slot:body="{ items }">
<tbody>
<tr v-for="item in items" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.business_Units }}</td>
<td>
<v-icon small class="mr-2" #click="editRole(item)">
mdi-pencil
</v-icon>
</td>
<td>{{ item.status | boolean }}</td>
</tr>
</tbody>
</template>
</v-data-table>
</template>
<script>
export default {
//..... chunk of my code on how to request from the api
created() {
SparrowService.getTeams()
.then((response) => {
this.loading = false;
this.teams = response.data;
})
.catch((error) => {
console.log(error.response);
});
},
};
</script>
item.business_Units is the array, so you need to take some action to join to the string.
Refer to Array.join()
...
<td>{{ item.business_Units.join(", ") }}</td>
...

Vue.js 2 filter is not working with data table

Attempting to filter data by the name of the client. Tried many options with no luck. currently i have the list of clients broken out to a separate component with intention to use vuex as the project becomes larger. So with that being said i have currently placed the logic for filtering inside my client info component where as the input for the search is in the clients list component. see below
this is the clients info component
<template>
<tbody class="client-info">
<tr v-for="(client, index) in filterClient" :key="index">
<td>{{ index }}</td>
<td>{{ client.name }}</td>
<td>{{ client.type }}</td>
<td>{{ client.email }}</td>
<td>{{ client.phone }}</td>
<td><router-link v-bind:to="'/client/'+client.id"><i class="far fa-eye"></i></router-link></td>
</tr>
</tbody>
</template>
<script>
export default {
name: 'client-info',
props: {
clients: {
type: Array,
default: () => []
}
},
data() {
return {
search: ''
}
},
created() {
this.$store.dispatch('retrieveClients')
},
computed: {
filterClient () {
return this.clients.filter( client => {
return !this.searchClient || client.name.toLowerCase().includes(this.searchClient.toLowerCase()) > -1
})
}
}
}
</script>
this is the clients list component
<template>
<div>
<!-- this is the head of the table list -->
<table class="table table-bordered table table-light table-striped table-hover">
<thead class="thead-primary">
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Type</th>
<th scope="col">Email</th>
<th scope="col">Phone</th>
<th scope="col">Profile</th>
</tr>
</thead>
<!-- the clients data is imported from client info file -->
<client-info :clients="allClients"></client-info>
</table>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import ClientInfo from '#/components/clientslistexperience/ClientInfo'
export default {
name: 'ClientsList',
components: {
ClientInfo
},
data() {
return {
search: null
}
},
computed: {
...mapGetters(['allClients']),
}
}
</script>
i am aware that the data for the search is placed in both components at the moment, just trying different things out. Also that right now it is not being set up to use vuex for the logic and state. If I am completely off track please let me know!
Table tag requires thead, tbody or tr . it removes other tag , so put table tag inside your component.
<template>
<div>
<client-info :clients="allClients"></client-info>
</div>
</template>
and put table tag along with all inner tag
<template>
<table class="table table-bordered table table-light table-striped table-hover">
<thead class="thead-primary">
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Type</th>
<th scope="col">Email</th>
<th scope="col">Phone</th>
<th scope="col">Profile</th>
</tr>
</thead>
<tbody class="client-info">
<tr v-for="(client, index) in filterClient" :key="index">
<td>{{ index }}</td>
<td>{{ client.name }}</td>
<td>{{ client.type }}</td>
<td>{{ client.email }}</td>
<td>{{ client.phone }}</td>
<td><router-link v-bind:to="'/client/'+client.id"><i class="far fa-eye"></i></router-link></td>
</tr>
</tbody>
</template>

VueJS performance issues with a table loaded from an array

I have a performance problem with VueJS. I have a table with X rows, which I load through an array. The problem is that when I change a single element of the array, it renders all the array again, and therefore, performs all the conditions again (v-if, if inside v-bind:class, etc.). I leave a jsfiddle where from a table, hide only 1 element, and update the whole table again.
https://jsfiddle.net/toledorobia/0twghfya/
$(function(){
var users = [];
for (var i = 1; i <= 100; i++) {
users.push({
id: i,
name: faker.name.findName(),
email: faker.internet.email(),
visible: true
});
}
var app = new Vue({
el: "#app",
data: {
users: users
},
methods: {
random: function() {
return faker.random.number();
},
toggleRows: function(){
this.users[5].visible = !$(this.$refs.togglerows).is(":checked");
}
}
});
});
<div id="app">
<div>
<input type="checkbox" ref="togglerows" v-on:click="toggleRows" /> Hide some rows
</div>
<table border="1" cellspacing="0">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="u in users" v-if="u.visible">
<td>{{ u.id + ' ' + random() }}</td>
<td>{{ u.name }}</td>
<td>{{ u.email }}</td>
</tr>
</tbody>
</table>
</div>
How can I avoid this behavior?
Thanks in advance.
Because everything is rendered in the same scope, when you show/hide the single row you want, Vue is forced to re-render all the rows. Instead, isolate the scope of the changes using a component.
Vue.component("row",{
props:["user"],
template:`
<tr>
<td>{{ user.id }}</td>
<td>{{random()}}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
</tr>`,
methods:{
random: function() {
return faker.random.number();
},
}
})
And your main template ends up looking like this:
<tbody>
<tr is="row" v-for="u in users" :key="u.id" v-if="u.visible" :user="u"></tr>
</tbody>
Here is the updated fiddle.