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

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>

Related

Vue.js making object.length value reactive

Trying to display Total records. Students.length works the first time on page load thanks to the created() method. However, calling filteredStudents(), is out of date. What is the easiest way to make this reactive?
<template>
<div class="d-inline-flex flex-row p-4 col-2">
Total record(s): {{ recordCount }}
</div>
<table class="table border table-striped table-hover">
<thead class="bg-secondary">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="student in filteredStudents()" :key="student._id">
<td>{{ student.firstName }}</td>
<td>{{ student.lastName }}</td>
<td>{{ student.email }}</td>
</tr>
</tbody>
</table>
</template>
<script>
import MixinCommon from '#/mixins/common.js'
export default {
data() {
return {
searchTerm: '',
Students: [],
studentcount: 0
}
},
created() {
this.Students = this.getSutdentList()
},
computed: {
recordCount() {
return this.Students.length
}
},
mixins: [MixinCommon],
methods: {
filteredStudents() {
return this.searchStudentList(this.searchTerm.toUpperCase(), this.Students)
},
}
}
</script>
I don't know the implementation of the searchStudentsList method, but you could try using the filteredStudents as a computed property, or making a watch property on the searchTerm in order to make the search again:
Using computed:
<template>
<div class="d-inline-flex flex-row p-4 col-2">
Total record(s): {{ recordCount }}
</div>
<table class="table border table-striped table-hover">
<thead class="bg-secondary">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="student in filteredStudents" :key="student._id">
<td>{{ student.firstName }}</td>
<td>{{ student.lastName }}</td>
<td>{{ student.email }}</td>
</tr>
</tbody>
</table>
</template>
<script>
import MixinCommon from '#/mixins/common.js'
export default {
data() {
return {
searchTerm: '',
Students: [],
studentcount: 0
}
},
created() {
this.Students = this.getSutdentList()
},
computed: {
recordCount() {
return this.Students.length
},
filteredStudents() {
return this.searchStudentList(this.searchTerm.toUpperCase(), this.Students)
},
},
mixins: [MixinCommon],
}
</script>
Using watch property:
<template>
<div class="d-inline-flex flex-row p-4 col-2">
Total record(s): {{ recordCount }}
</div>
<table class="table border table-striped table-hover">
<thead class="bg-secondary">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="student in filteredStudents" :key="student._id">
<td>{{ student.firstName }}</td>
<td>{{ student.lastName }}</td>
<td>{{ student.email }}</td>
</tr>
</tbody>
</table>
</template>
<script>
import MixinCommon from '#/mixins/common.js'
export default {
data() {
return {
searchTerm: '',
Students: [],
filteredStudents: [],
studentcount: 0
}
},
created() {
this.Students = this.getSutdentList()
this.filteredStudents = this.searchStudentList(this.searchTerm.toUpperCase(), this.Students)
},
computed: {
recordCount() {
return this.Students.length
}
},
watch: {
searchTerm(newValue) {
this.filteredStudents = this.searchStudentList(newValue.toUpperCase(), this.Students)
}
}
mixins: [MixinCommon],
}
</script>

vue - datatable - item-expanded - load from server

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.

How to bind data from parent to child component inside v-for

So i have a modal components like this
<el-dialog title="Shipping address" :visible.sync="dialogTableVisible">
<table>
<tr>
<th style="width:300px">Description</th>
<th style="width:300px">Quantity</th>
<th style="width:300px">Unit Price</th>
<th style="width:300px">Amount (Rp. )</th>
</tr>
<tr v-for="(item, ind) in invoiceDetails.chargesList" :key="ind" class="h-2">
<td>{{ item.description }}</td>
<td>{{ item.qty }}</td>
<td>{{ item.unitPrice }}</td>
<td>{{ item.totalPrice }}</td>
</tr>
<tr v-for="(invoiceProduct, k) in invoiceProducts" :key="k">
<td>
{{ invoiceProduct.name }}
</td>
<td>
{{ invoiceProduct.qty }}
</td>
<td>
{{ invoiceProduct.price }}
</td>
<td>
{{ invoiceProduct.lineTotal }}
</td>
</tr>
<tr class="h-2">
<td>Subtotal :</td>
<td>{{ subtotalCharges }}</td>
</tr>
<tr class="h-2">
<td>Tax(10%) :</td>
<td>{{ taxedCharges }}</td>
</tr>
<tr class="h-2">
<td>Total :</td>
<td>{{ totalCharges }}</td>
</tr>
</table>
and as you can see there are 2 v-for. How do i bind the data from the parent component? the first loop is data that i get from an api, and the second is from a dynamically adding a row
this the parent component:
<template>
<div>
<PreviewModal
:dialogTableVisible="dialogTableVisible"/>
</div>
</template>
<script>
export default {
data() {
return {
invoiceProducts: []
}
}
}
</script>
the "invoiceProducts" will be filled with by adding a new row of table and here's the json:
"chargesList": [
{
"description": "Ocean Freight (Measurement: 5.75 CBM)",
"qty": "1",
"unitPrice": "57.5",
"unitBy": "-",
"totalPrice": "57.5"
},
{
"description": "Charge1",
"qty": "1",
"unitPrice": "10",
"unitBy": "-",
"totalPrice": "10"
},
{
"description": "Fast",
"qty": "1",
"unitPrice": "20",
"unitBy": "-",
"totalPrice": "20"
}
]

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>

validate Min option of integer field in Symfony2.1 application

I created my form with this code :
public function creerConferenceAction($id = null) {
$message = '';
if (isset($id)) {
$conference = $this->getDoctrine()
->getRepository('gestionConferenceApplicationBundle:Conference')
->find($id);
if (!$conference) {
throw $this->createNotFoundException('No conference found for id ' . $id);
}
}else{
$conference = new Conference();
}
$form = $this->createFormBuilder($conference)
->add('titre', 'text')
->add('ville', 'text')
->add('lieu', 'text')
->add('date_debut', 'date', array(
'widget' => 'single_text',
'format' => 'yyyy-MM-dd',
))
->add('date_fin', 'date')
->add('nbMin', 'integer')
->add('nbMax', 'integer')
->add('dateLimiteInscription', 'date')
->getForm();
$request = $this->getRequest();
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($conference);
$em->flush();
return $this->redirect($this->generateUrl('_acceuil'));
}
}
return $this->render('gestionConferenceApplicationBundle:acceuil:creerConference.html.twig', array(
'form' => $form->createView(),
));
}
and I want to add this constraint : the user cannot enter a value less than 5 in those fields :
->add('nbMin', 'integer')
->add('nbMax', 'integer')
I tested this (I take it from the reference book) :
# src/gestionConference/ApplicationBundle/Resources/config/validation.yml
gestionConference\ApplicationBundle\Entity\Conference:
properties:
age:
- Min: { limit: 18, message: You must be 18 or older to enter. }
but it do nothing
how can I achieve this
thank you in advance
-------------------EDIT-------------------EDIT------------------------------
I read another time the reference and I realized that the min option is removed in the latest version of symfony 2.1.3
and I replaced it by :
# src/gestionConference/ApplicationBundle/Resources/config/validation.yml
gestionConference\ApplicationBundle\Entity\Conference:
properties:
nbmin:
- Range:
min: 120
minMessage: You must be at least 120cm tall to enter
but no change
here is the twig page :
{% extends "gestionConferenceApplicationBundle::layout.html.twig" %}
{% block content %}
<div id="welcome">
<div class="content">
<form action="" method="post" {{ form_enctype(form) }}>
{{ form_errors(form) }}
<table>
<tr>
<td>{{ form_label(form.titre, 'Titre : ') }}</td>
<td>{{ form_widget(form.titre) }}</td>
<td>{{ form_errors(form.titre) }}</td>
</tr>
<tr>
<td>{{ form_label(form.ville, 'Ville : ') }}</td>
<td>{{ form_widget(form.ville) }}</td>
<td>{{ form_errors(form.ville) }}</td>
</tr>
<tr>
<td>{{ form_label(form.lieu, 'Lieu : ') }}</td>
<td>{{ form_widget(form.lieu) }}</td>
<td>{{ form_errors(form.lieu) }}</td>
</tr>
<tr>
<td>{{ form_label(form.date_debut, 'Date de début : ') }}</td>
<td>{{ form_widget(form.date_debut) }}</td>
<td>{{ form_errors(form.date_debut) }}</td>
</tr>
<tr>
<td>{{ form_label(form.date_fin, 'Date de fin : ') }}</td>
<td>{{ form_widget(form.date_fin) }}</td>
<td>{{ form_errors(form.date_fin) }}</td>
</tr>
<tr>
<td>{{ form_label(form.nbMin, 'Nombre minimal de participants : ') }}</td>
<td>{{ form_widget(form.nbMin) }}</td>
<td>{{ form_errors(form.nbMin) }}</td>
</tr>
<tr>
<td>{{ form_label(form.nbMax, 'Nombre maximal de participants : ') }}</td>
<td>{{ form_widget(form.nbMax) }}</td>
<td>{{ form_errors(form.nbMax) }}</td>
</tr>
<tr>
<td>{{ form_label(form.dateLimiteInscription, 'Date limite d inscription : ') }}</td>
<td>{{ form_widget(form.dateLimiteInscription) }}</td>
<td>{{ form_errors(form.dateLimiteInscription) }}</td>
</tr>
{{ form_rest(form) }}
<tr>
<td align="center" colspan=3 >
<input type="submit" style="width: 80px;height: 30px;margin-right: 25px;" value="valider" />
<input type="reset" style="width: 80px;height: 30px;" value="initialiser" />
</td>
</tr>
</table>
</form>
</div>
</div>
{% endblock %}