How to add pagination in api driven vue app? - vue.js

I have a get api that looks like this -
this.$API +"api/v1/puzzles/getAll?page=" + this.pageNo +"&limit=" + this.pageLimit,
It accepts two params page and limit. How to make pagination for this get api ?
My html code:
<md-card>
<md-card-header data-background-color="green">
<h4 class="title">List of Puzzles</h4>
<p class="category">The list of puzzles you have uploaded</p>
</md-card-header>
<md-card-content class="justify-content-center">
<table>
<thead>
<tr>
<th><b>Puzzle Question</b></th>
<th><b>Option 1</b></th>
<th><b>Option 2</b></th>
<th><b>Option 3</b></th>
<th><b>Option 4</b></th>
<th><b>Correct Answer</b></th>
<th><b>Action</b></th>
</tr>
</thead>
<tbody>
<tr v-for="(data, index) in puzzleList.puzzles" :key="index">
<td class="q-img"><img :src="data.qImage" alt="" /></td>
<td
class="ans-img"
v-for="(collection, index) in data.qOptions"
:key="index"
>
<img :src="collection.oImage" alt="" />
</td>
<td style="padding-left: 32px">
<h2>{{ data.qAnswer }}</h2>
</td>
<router-link to="/editPuzzle"
><td style="padding-top: 70px">
<button class="btn btn-success">Edit</button>
</td></router-link
>
<td>
<button
v-on:click="deletePuzzle(data.id)"
class="btn btn-danger"
>
Delete
</button>
</td>
</tr>
</tbody>
<!-- <pagination v-model="pageNo" :pageLimit="500" #paginate="myCallback"/> -->
</table>
</md-card-content>
</md-card>
data() {
return {
siteURL: this.$axios.defaults.siteURL,
puzzleList: [],
pageNo: 1,
pageLimit: 4,
token: localStorage.getItem("_token"),
puzzleId: "",
};
},
I tried to use third-party packages but couldnt make it work. I have taken 2 variables inside return above like pageNo: 1 and pageLimit: 4 and haven't found any solution anywhere with this type of api. Please show me detaily, how should I implement this ?
Update:
<table>
<thead>
<tr>
<th><b>Puzzle Question</b></th>
<th><b>Option 1</b></th>
<th><b>Option 2</b></th>
<th><b>Option 3</b></th>
<th><b>Option 4</b></th>
<th><b>Correct Answer</b></th>
<th><b>Action</b></th>
</tr>
</thead>
<tbody>
<tr v-for="(data, index) in puzzleList.puzzles" :key="index">
<td class="q-img"><img :src="data.qImage" alt="" /></td>
<td
class="ans-img"
v-for="(collection, index) in data.qOptions"
:key="index"
>
<img :src="collection.oImage" alt="" />
</td>
<td style="padding-left: 32px">
<h2>{{ data.qAnswer }}</h2>
</td>
<router-link to="/editPuzzle"
><td style="padding-top: 70px">
<button class="btn btn-success">Edit</button>
</td></router-link
>
<td>
<button
v-on:click="deletePuzzle(data.id)"
class="btn btn-danger"
>
Delete
</button>
</td>
</tr>
<pagination
v-model="pageNo"
:pageLimit="4"
#paginate="myCallback"
/>
</tbody>
</table>
methods:{
myCallback(e) {
this.pageNo = e;
this.getPuzzle();
},
getPuzzle: function () {
this.$axios
.get(
this.$API +
"api/v1/puzzles/getAll?page=" +
this.pageNo +
"&limit=" +
this.pageLimit,
{
headers: {
Authorization: "Bearer " + this.token,
},
}
)
.then((res) => {
this.puzzleList = res.data.data;
this.puzzleId = res.data.data.puzzles[0].id;
console.log(this.puzzleId);
});
},

any third-party of pagination api has the property that you should set the current page and the limit or total, the main of pagination is that current page,page size, total and the callback of current page changes, the lifecycle is that:
init: you fetch the api with the params(currentpage, pagesize) to get data, then according to your response ,you can get the total count of your data
use the 1 step response like total count, and give it to your pagination component
don't forget to declare your onChange callback ,which the pagination component necessary to use, in the callback ,you just change the current page which user click and fetch your api again to get the new data.

Related

change button switch toggle in vuejs

I have a button that when I click it changes the status of the record, but when I update, the color of the button does not change, if I refresh the page if it changes, how can I make the button change when I update the record
Table:
<div class="card-body">
<table id="tblProfiles" class="table table-bordered table-hover dt-responsive">
<thead>
<tr>
<th>Description</th>
<th>Status</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr v-for="(profile, index) in profiles" :key="index">
<td>{{ profile.description }}</td>
<td>
<button
class="btn-sm"
:class="[profile.status == 1 ? 'btn-success' : 'btn-danger']"
#click="statusUpdate(profile.id)"
>{{profile.status == 1 ? 'Active' : 'Inactive'}}
</button>
</td>
<td>
<button class="btn btn-info btn-sm">Details</button>
</td>
</tr>
</tbody>
</table>
</div>
Method:
// ...
statusUpdate: async function(id) {
try {
const response = await profileService.activateDesactivate(id);
console.log(response);
} catch (error) {
console.log(error);
}
}
Send profile object insted of id prop:
<div class="card-body">
<table id="tblProfiles" class="table table-bordered table-hover dt-responsive">
<thead>
<tr>
<th>Description</th>
<th>Status</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr v-for="(profile, index) in profiles" :key="index">
<td>{{ profile.description }}</td>
<td>
<button
class="btn-sm"
:class="[profile.status == 1 ? 'btn-success' : 'btn-danger']"
#click="statusUpdate(profile)"
>{{profile.status == 1 ? 'Active' : 'Inactive'}}
</button>
</td>
<td>
<button class="btn btn-info btn-sm">Details</button>
</td>
</tr>
</tbody>
</table>
</div>
Method receives profile objetc and update it as you want. In your case status prop changes the color class of your button.
statusUpdate: async function(profile) {
try {
const response = await profileService.activateDesactivate(profile.id);
profile.status = 1;
console.log(response);
} catch (error) {
console.log(error);
}
},

How to get the ID from a table inside a b-modal and display on the page in VUEJS

I am facing issue where i want to get the ID from the table when clicking on the button inside a modal and display it on the main page.
Here is the HTML code
<template>
<div class="hello">
<p>Selected id :</p>
<b-button class="mt-2" variant="primary" v-b-modal.modal-xl>
Select codes
</b-button>
<b-modal id="modal-xl" size="lg" centered hide-footer="true">
<table class="table sortable" data-page-list="[10, 25, 50, 100, all]">
<thead>
<tr>
<th>ID</th>
<th>Code</th>
<th>Button</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2222</td>
<td>
<b-button variant="primary">Select</b-button>
</td>
</tr>
<tr>
<td>2</td>
<td>33333</td>
<td>
<b-button variant="primary">Select</b-button>
</td>
</tr>
<tr>
<td>3</td>
<td>4444</td>
<td>
<b-button variant="primary">Select</b-button>
</td>
</tr>
</tbody>
</table>
</b-modal>
</div>
</template>
Here is the Codesandbox for it.
Any help much appreciated.
One way to do that is to save the selected ID as the local state. In addition, I'd recommend using v-for and an array to store the codes list, and then you can pass the id to the event:
<template>
<div class="hello">
<p>Selected id: {{ selected }}</p>
<b-button class="mt-2" variant="primary" v-b-modal.modal-xl>
Select codes
</b-button>
<b-modal id="modal-xl" size="lg" centered hide-footer="true">
<table class="table sortable" data-page-list="[10, 25, 50, 100, all]">
<thead>
<tr>
<th>ID</th>
<th>Code</th>
<th>Button</th>
</tr>
</thead>
<tbody>
<tr v-for="code in codes" :key="code.id">
<td>{{ code.id }}</td>
<td>{{ code.code }}</td>
<td>
<b-button variant="primary" #click="onSelected(code.id)">Select</b-button>
</td>
</tr>
</tbody>
</table>
</b-modal>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
data() {
return {
codes: [
{id: 1, code: 2222},
{id: 2, code: 3333},
{id: 3, code: 4444},
],
selected: null
}
},
methods: {
onSelected: function(id) {
this.selected = id;
}
}
};
</script>
You can check out a working example here.

Is Vue 3 backwards compatible with Vue 2?

In different posts around the internet (for example this one) I found that Vue 2 code should work with Vue 3 but for me it does not. For example I have simple component
<template>
<div class="overflow-x-auto bg-white rounded-lg shadow overflow-y-auto relative">
<table class="table">
<thead>
<tr class="text-left">
<th>
<label>
<input type="checkbox">
</label>
</th>
<th>User ID</th>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
<th>Gender</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<label>
<input type="checkbox" name="1">
</label>
</td>
<td> <span>{{ id }}</span> </td>
<td> <span>Cort</span> </td>
<td> <span>Tosh</span> </td>
<td> <span>{{ email }}</span> </td>
<td> <span>Male</span> </td>
<td> <span>327-626-5542</span> </td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
id: 1,
email: 'test#mail.com'
}
},
mounted() {
alert('mounted');
},
created() {
alert('created');
}
};
</script>
The table is generated just fine, but both mounted and created not fired when component made. Also the email and id not shown. Only the table is shown.
Your code works:
Vue.createApp({
data() {
return {
id: 1,
email: 'test#mail.com'
}
},
created() {
alert('created')
},
mounted() {
alert('mounted')
}
}).mount('#app')
<script src="https://unpkg.com/vue#next"></script>
<div id="app" class="overflow-x-auto bg-white rounded-lg shadow overflow-y-auto relative">
<table class="table">
<thead>
<tr class="text-left">
<th>
<label>
<input type="checkbox">
</label>
</th>
<th>User ID</th>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
<th>Gender</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<label>
<input type="checkbox" name="1">
</label>
</td>
<td> <span>{{ id }}</span> </td>
<td> <span>Cort</span> </td>
<td> <span>Tosh</span> </td>
<td> <span>{{ email }}</span> </td>
<td> <span>Male</span> </td>
<td> <span>327-626-5542</span> </td>
</tr>
</tbody>
</table>
</div>

Setting a Form Value in Vue Js

I am using Struts 1.x in my application. Recently i used Vue js.So, I use the same jsp page for Adding and updating (in this case company). So When i click edit, the details are fetched the page is redirected to that page and form values are set from the action class.
Here is the html portion
<form action="company.do" method="post" name="companyForm">
<html:hidden property="method" value="doAddUpdateCompany" />
<html:hidden property="companyId" value="${companyForm.companyId}" />
<div class="row" >
<div class="col-md-9">
<div class="grid simple">
<div class="grid-title ">
<h4>
<logic:equal value="addCompany" property="method" name="companyForm">
New <span class="semi-bold">Company</span>
</logic:equal>
<logic:equal value="updateCompany" property="method" name="companyForm">
Edit <span class="semi-bold">Company</span>
</logic:equal>
</h4>
<div class="tools"> </div>
</div>
<div class="grid-body">
<table class="tbl_wall" style="width: 100%" >
<tr >
<td class="fi_wall" >Company Name<span class="notify style16"> *</span></td>
<td class="fi_wall" ><html:text property="companyName" name="companyForm" styleClass="med_txt" /></td>
<td> </td>
</tr>
<tr>
<td class="fi_wall" valign="top" >Company Code<span class="notify style16"> *</span> (3 Letter)</td>
<td class="fi_wall" valign="middle" ><html:text property="companyCode" maxlength="3" styleClass="med_txt" name="companyForm" /></td>
<td> </td>
</tr>
<tr id="cmp">
<td class="fi_wall">Company Type </td>
<td class="fi_wall"><select name="companyType" v-model="companyType">
<option value="-1">select</option>
<option v-for=" result in results " v-bind:value="result.commonId">
{{ result.name}}</option>
</select></td>
</tr>
<tr>
<td colspan="3" align="center">
<button type="button" class="btn btn-success" onclick="doSave()" ><i class="fa fa-save"></i> Save</button>
</td>
</tr>
</table> </form>
and the vue Portion
<script type="text/javascript">
new Vue({
el: '#cmp',
data: {
results: [],
companyType : '-1'
},
mounted() {
axios.get('/easyoffice/companyType.do?method=getCompanyTypeAjax').then(response => {
this.results = response.data,
this.companyType = document.forms['companyForm'].companyType.value
})
.catch(e => {
this.errors.push(e)
})
}
});</script>
i used this.companyType = document.forms['companyForm'].companyType.value to set form value but it is not working. Any Thoughts?

Vuejs: add the same form multiple times

I'm using laravel and vuejs.
One of the things I want to be able to do, is to allow the user to create muliple address when they click the button.
Here the sample code:
<table>
<tr>
<th>POSTAL CODE</th>
<td><input type="text" name="postal_code[]" v-model="" /></td>
</tr>
<tr>
<th>City</th>
<td>
<select name="city[]" v-model="">
<option>ABC</option>
</select>
</td>
</tr>
<tr>
<th>District</th>
<td><input type="text" name="District[]" v-model="" /></td>
</tr>
<tr>
<th>Street</th>
<td><input type="text" name="Street[]" v-model="" /></td>
</tr>
<tr>
<th>Name/th>
<td>
last_name<input type="text" name="last_name[]" v-model="" />
first_name<input type="text" name="first_name[]" v-model="" />
</td>
</tr>
</table>
<button v-on:click="add-form">ADD</button>
EDIT Sorry because my question was not clear enough.
I want to duplicate the whole table, not only one input, and everytime user click the button, i want to show one more table (the old table with old input has not be changed)
I found the solution.
Thank you so much!
All you need to do is to create an empty array of addresses and then push the input into this array on button click. Here's an example:
Jsfiddle: https://jsfiddle.net/zyh4jvuf/
<div id="app">
<input type="text" v-model="addressInput">
<button v-on:click="addAddress">add</button>
<!-- Displaying addresses -->
<div v-for="address in addresses">
{{address}}
</div>
</div>
new Vue({
el: '#app',
data () {
return {
addressInput: '',
addresses: []
}
},
methods: {
addAddress () {
this.addresses.push(this.addressInput)
// clear the input
this.addressInput = ''
}
}
})
Do you want to "duplicate" the whole table or just a single input? I guess the second want. In that case, i would rather push the info to an array like this:
<template>
<div class="formApp">
<input type="text" name="steet" v-model="street">
<button #click="addStreet">add</button>
<div v-for="str in streetArray">
<div #click="removeStreet($event)">{{ str }}</div>
</div>
</div>
</template>
<script>
export default {
name: 'formApp',
data() {
return {
streetArray: [],
street: '',
}
},
methods: {
addStreet() {
this.streetArray.push(this.street);
this.street = '';
},
removeStreet(event) {
var index = this.streetArray.indexOf(event.target.innerText);
index > -1 ? this.streetArray.splice(index, 1):'';
}
}
}
</script>
The addStreet will add a new street everytime you click the button and then it will clear the input. Then, if the user wants to delete the street, it will have to click over the street name. That way of deleting things is not user friendly at all so you could add a icon to each street name to declare that possibility.
Also, it was just an hint for you because there can be errors while writing streets names and the user needs a way to delete them. Having a bunch of inputs for wrong streets or not being able to delete the ones you added would be a total chaos. Anyways, there you go.
You can try the following code
new Vue({
el: '#example-3',
data:{
title:"Lists",
item:{},
items:[]
},
methods: {
addform: function () {
this.items.push(this.item);
this.item={};
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="example-3">
<table>
<tr>
<th>POSTAL CODE</th>
<td><input type="text" name="postal_code" v-model="item.postal_code" /></td>
</tr>
<tr>
<th>City</th>
<td>
<select name="city" v-model="item.city">
<option>ABC</option>
</select>
</td>
</tr>
<tr>
<th>District</th>
<td><input type="text" name="District" v-model="item.District" /></td>
</tr>
<tr>
<th>Street</th>
<td><input type="text" name="Street" v-model="item.Street" /></td>
</tr>
<tr>
<th>Name</th>
<td>
last_name<input type="text" name="last_name" v-model="item.last_name" /><br/>
first_name<input type="text" name="first_name" v-model="item.first_name" />
</td>
</tr>
</table>
<button v-on:click="addform">ADD</button>
<br/>
<h2>{{title}}</h2>
<table border="1" v-if="items.length>0">
<tr v-for="(value,index) in items">
<td>{{value.postal_code}}</td>
<td>{{value.city}}</td>
<td>{{value.District}}</td>
<td>{{value.last_name}}</td>
<td>{{value.first_name}}</td>
</tr>
</table>
</div>