vue selectall checkbox indeterminate binding - vue.js

i have a table like this what i want to do is apply indeterminate.prop, so if all are selected, checkbox is checked,if even 1 checkbox is checked :indeterminate.prop
I want to apply. How can I write this? I couldn't write the condition.
Frankly, not being able to write a simple and easy condition with vue js made me a little nervous.
stackoverflow asks for a lot of details but I don't know what to write
new Vue({
el: "#app",
data: {
selected: [],
messages: [{
id: 1,
text: "Learn JavaScript",
status: 'read'
},
{
id: 2,
text: "Learn Vue",
status: 'unread'
},
{
id: 3,
text: "Play around in JSFiddle",
status: 'read'
},
{
id: 4,
text: "Build something awesome",
status: 'unread'
}
]
},
computed: {
selectAll: {
get: function() {
return this.messages ? this.selected.length == this.messages.length : false;
},
set: function(value) {
var selected = [];
if (value) {
this.messages.forEach(function(item) {
selected.push(item.id);
});
}
this.selected = selected;
}
}
},
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<table class="table">
All,
<thead>
<tr>
<th><input type="checkbox" v-model="selectAll"></th>
<th>Status</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in messages">
<td><input type="checkbox" v-model="selected" :value="item.id"></td>
<td>{{ item.status }}</td>
<td>{{ item.text }}</td>
</tr>
</tbody>
</table>
</div>

To select and unselect all checkboxes, you need to remove that computed properly and add a click event, which all ids, or remove all ids from selected.
new Vue({
el: "#app",
data: {
selected: [],
messages: [{
id: 1,
text: "Learn JavaScript",
status: 'read'
},
{
id: 2,
text: "Learn Vue",
status: 'unread'
},
{
id: 3,
text: "Play around in JSFiddle",
status: 'read'
},
{
id: 4,
text: "Build something awesome",
status: 'unread'
}
]
},
methods: {
selectAll(){
if(this.selected.length !== this.messages.length){
this.selected = this.messages.map(e=>e.id)
}else {
this.selected = []
}
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h1>Selected ids: {{ selected }}</h1>
<button #click="selectAll">{{selected.length === messages.length ?'Unselect all' : 'Select All' }}</button>
<table class="table">
<thead>
<tr>
<th>Status</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in messages">
<td><input type="checkbox" v-model="selected" :value="item.id"></td>
<td>{{ item.status }}</td>
<td>{{ item.text }}</td>
</tr>
</tbody>
</table>
</div>

Related

Vue Sorted Table (Sorted from highest to lowest)

Hi i am a newbie in vuejs. I wanted to sort a table by Highest to lowest. However i install the library of vue-sorted-table. But when im trying run the code the data always return lowest to highest. Can anyone help me? Thank you..
Here is the code:
<template>
<div id="app">
<sorted-table :values="values" #sort-table="onSort">
<thead>
<tr>
<th scope="col" style="text-align: left; width: 10rem;">
<sort-link name="id">ID</sort-link>
</th>
</tr>
</thead>
<template #body="sort">
<tbody>
<tr v-for="value in sort.values" :key="value.id">
<td>{{ value.id }}</td>
</tr>
</tbody>
</template>
</sorted-table>
</div>
</template>
<script>
import { ChevronUpIcon } from "vue-feather-icons";
export default {
name: "App",
data: function() {
return {
values: [{ id: 2 }, { id: 1 }, { id: 3 }],
sortBy: "",
sortDir: ""
};
},
components: {
ChevronUpIcon
},
methods: {
onSort(sortBy, sortDir) {
this.sortBy = sortBy;
this.sortDir = sortDir;
}
}
};
</script>
<style>
.feather {
transition: 0.3s transform ease-in-out;
}
.feather.asc {
transform: rotate(-180deg);
}
</style>
code can access here:
https://codesandbox.io/s/pedantic-kirch-bx9zv
Add dir property to sorted-table, and make its value equals to desc
<template>
<div id="app">
<sorted-table :values="values" #sort-table="onSort" dir="desc">
<thead>
<tr>
<th scope="col" style="text-align: left; width: 10rem;">
<sort-link name="id">ID</sort-link>
</th>
</tr>
</thead>
<template #body="sort">
<tbody>
<tr v-for="value in sort.values" :key="value.id">
<td>{{ value.id }}</td>
</tr>
</tbody>
</template>
</sorted-table>
</div>
</template>
<script>
import { ChevronUpIcon } from "vue-feather-icons";
export default {
name: "App",
data: function() {
return {
values: [{ id: 2 }, { id: 1 }, { id: 3 }],
sortBy: "",
sortDir: ""
};
},
components: {
ChevronUpIcon
},
methods: {
onSort(sortBy, sortDir) {
this.sortBy = sortBy;
this.sortDir = sortDir;
}
}
};
</script>
<style>
.feather {
transition: 0.3s transform ease-in-out;
}
.feather.asc {
transform: rotate(-180deg);
}
</style>
check https://github.com/BernhardtD/vue-sorted-table and pay attention to dir property of the table, you'll find the answer

How to select All checkboxes based on condition with Vue.js

I am trying to select checkboxes based on some condition.
Select all checkboxes (select all checkboxes)
select all unread (select all unread where data array has status of
unread)
select all read (select all read where data array has status of read)
I am able to select all checkboxes on checkbox click,but unable to select it with links
I also need to fetch the ids of selected checkboxes,so i can perform action against these selected checkboxes.
Can you guys please have a look at this.
new Vue({
el: "#app",
data: {
selected: [],
messages: [{
id: 1,
text: "Learn JavaScript",
status: 'read'
},
{
id: 2,
text: "Learn Vue",
status: 'unread'
},
{
id: 3,
text: "Play around in JSFiddle",
status: 'read'
},
{
id: 4,
text: "Build something awesome",
status: 'unread'
}
]
},
methods: {
},
computed: {
selectAll: {
get: function() {
return this.messages ? this.selected.length == this.messages.length : false;
},
set: function(value) {
var selected = [];
if (value) {
this.messages.forEach(function(item) {
selected.push(item.id);
});
}
this.selected = selected;
}
}
},
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h2>Message App:</h2>
<table class="table">
All,
Read,
Unread,
<thead>
<tr>
<th><input type="checkbox" v-model="selectAll"></th>
<th>Status</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in messages">
<td><input type="checkbox" v-model="selected" :value="item.id"></td>
<td>{{ item.status }}</td>
<td>{{ item.text }}</td>
</tr>
</tbody>
</table>
</div>
You might want to use click event on a element:
All,
and in javascript code:
methods: {
selectAllHandler() {
if (this.selected.length) {
this.selected = []
} else {
this.selected = this.messages.map(item => item.id);
}
}
}
Your Javascript:
new Vue({
el: "#app",
data: {
selected: [],
messages: [{
id: 1,
text: "Learn JavaScript",
status: 'read'
},
{
id: 2,
text: "Learn Vue",
status: 'unread'
},
{
id: 3,
text: "Play around in JSFiddle",
status: 'read'
},
{
id: 4,
text: "Build something awesome",
status: 'unread'
}
]
},
methods: {
selectAll() {
this.selected = this.messages.map((message) => message.id);
}
}
})
Your HTML:
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h2>Message App:</h2>
<table class="table">
All,
Read,
Unread,
<thead>
<tr>
<th><input type="checkbox" v-model="selectAll"></th>
<th>Status</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in messages">
<td><input type="checkbox" v-model="selected" :value="item.id"></td>
<td>{{ item.status }}</td>
<td>{{ item.text }}</td>
</tr>
</tbody>

Looping a component in another component Vue.js

The question here is how can I get this Task.vue file to loop in my tasklist.vue file knowing I'm willing to pass a json file so I can get the list of all the task to do.
Task.vue
<template>
<table :id="id" class="task_box">
<tr>
<td class="task_user">{{name}}</td>
<td class="task_date">{{date}}</td>
<td class="task_time">{{time}}</td>
</tr>
<tr>
<td colspan="3" class="task_description">
<div class="toto">{{description}}</div>
</td>
</tr>
</table>
</template>
<script>
export default {
name: "task",
data() {
return {
id: 1,
name: "Test",
date: new Date(),
time: "9:30 ",
description: "whatever"
};
}
};
</script>
So this task.vue is meant to be a container that I can use in the tasklist.vue.
tasklist.vue
<template>
<div>
<task v-for="task in tasks" :key="task.id"></task>
</div>
</template>
<script>
import Task from "./Task.vue";
export default {
name: "tasklist",
data() {
return {
tasks: []
};
},
components: {
Task
}
};
</script>
You need to use Properties to pass your task from your task list to your task. Code is untested.
#Task
<template>
<table :id="task.id" class="task_box">
<tr>
<td class="task_user">{{task.name}}</td>
<td class="task_date">{{task.date}}</td>
<td class="task_time">{{task.time}}</td>
</tr>
<tr>
<td colspan="3" class="task_description">
<div class="toto">{{description}}</div>
</td>
</tr>
</table>
</template>
<script>
export default {
name: "task",
props: ["task"],
};
</script>
#TaskList
<template>
<div>
<task v-for="task in tasks" :task="task" :key="task.id"></task>
</div>
</template>
<script>
import Task from "./Task.vue";
export default {
name: "tasklist",
data() {
return {
tasks: [{
id: 1,
name: "Test",
date: new Date(),
time: "9:30 ",
description: "whatever"
}]
};
},
components: {
Task
}
};
</script>
If task-component is reapeating, you should insert it's tag inside table tag.
Use props to pass data to task-component from tasklist-component
When tasklist-component is creating, you can load tasks via Ajax from json.
Full working example of code you can find here
TaskList.vue
<script>
import Task from "./Task.vue";
export default {
components: { Task },
data() {
return {
tasks: [],
isLoading: false,
doShowNewTaskAddingDialog: false,
};
},
created(){
// this.isLoading = true;
// $.ajax({
// url: '/some/tasks/url',
// method: 'GET',
// dataType: 'json',
// success: (tasks) => {
// this.isLoading = false;
// this.tasks = tasks;
// }
// });
this.tasks = [
{id: 1, name: "task 1", date: new Date(), time: "9:31", description: "descr 1" },
{id: 1, name: "task 2", date: new Date(), time: "9:32", description: "descr 2" },
{id: 1, name: "task 3", date: new Date(), time: "9:33", description: "descr 3" },
{id: 1, name: "task 4", date: new Date(), time: "9:34", description: "descr 4" },
]
},
methods:{
addButtonHandler(){
this.doShowNewTaskAddingDialog = true;
}
}
};
</script>
<template>
<div>
<div v-if="isLoading">Please wait, loading tasks...</div>
<table v-if="!isLoading">
<task
v-for="task in tasks"
:key="task.id"
:task="task"
:isNew="false"
/>
<task
v-if="doShowNewTaskAddingDialog"
:isNew="true"
/>
</table>
Add new?
</div>
</template>
<style>
table, td{
border-collapse: collapse;
border: 1px solid black;
}
</style>
Task.vue
<template>
<!--
I'd prefer use bootstrap row and col- divs here instead
of table and tbody-hack. See discussion here: https://github.com/vuejs/Discussion/issues/295
-->
<tbody>
<!-- display only -->
<tr v-if="!isNew">
<td class="task_user">{{name}}</td>
<td class="task_date">{{date}}</td>
<td class="task_time">{{time}}</td>
</tr>
<tr v-if="!isNew">
<td colspan="3" class="task_description">
<div class="toto">{{description}}</div>
</td>
</tr>
<!-- edit -->
<tr v-if="isNew">
<td class="task_user"><input type="text" v-model="name"></td>
<td class="task_date"><input type="text" v-model="date"></td>
<td class="task_time"><input type="text" v-model="time"></td>
</tr>
<tr v-if="isNew">
<td colspan="3" class="task_description">
<div class="toto"><input type="text" v-model="description"></div>
</td>
</tr>
</tbody>
</template>
<script>
export default {
props:{
task: { type: Object, required: false },
isNew: { type: Boolean, required: true },
},
created(){
if(!this.isNew){
this.id = this.task.id;
this.name = this.task.name;
this.date = this.task.date;
this.time = this.task.time;
this.description = this.task.description;
}
},
data() {
return {
id: 1,
name: "",
date: new Date(),
time: "0:00 ",
description: ""
};
}
};
</script>

Vuejs Ajax call and dataTable

I'm using Vuejs and dataTable for one of my project. I make an Ajax call and push data into an array. After that I use v-for to loop the data in the <tr> tag. Most of the time it doesn't work. The table loads as soon as the page has finished loading.. it takes a bit of time to receive the ajax data. Here is the output. It says no data available in the table
So the serch option doesn't work properly. I thought to use a setTimeout function (which was a bad idea) to load the table after a bit of time. What would be the proper way to do it? Sharing the code :
new Vue({
el: '#app',
data: {
entries: [],
},
methods:{
getData(){
var route = '/admin/temporary-enrolled-students';
this.$http.get(route).then((response)=>{
for(var i = 0; i< response.data.length;i++)
{
this.entries.push({
scId: response.data[i].id,
name: response.data[i].user.name,
phone: response.data[i].user.phone,
email: response.data[i].user.email,
courseId: response.data[i].course.id,
courseName: response.data[i].course.course_title,
expiryDate: response.data[i].expiry_date,
shares: response.data[i].number_of_shares,
expired: (response.data[i].expired == 1),
enrollDate: response.data[i].created_at
})
}
})
},
},
mounted(){
this.getData();
},
});
//data table
$(function () {
setTimeout(()=> {
$("#temp-enroll").DataTable({
"paging": true,
"ordering": false,
"info": true,
"autoWidth": false
});
},1000);
});
in blade:
Ok I tried this and working exactly what I have wanted. Thanks everyone for supporting.
new Vue({
el: '#app',
data: {
entries: [],
},
methods:{
getData(){
var route = '/admin/temporary-enrolled-students';
this.$http.get(route).then((response)=>{
for(var i = 0; i< response.data.length;i++)
{
this.entries.push({
scId: response.data[i].id,
name: response.data[i].user.name,
............................
......................
enrollDate: response.data[i].created_at
})
}
}).then(()=>{
$("#temp-enroll").DataTable({
"paging": true,
"ordering": false,
"info": true,
"autoWidth": false
});
});
},
},
mounted(){
this.getData();
},
});
I think someone mentioned that a computed property is the way to go, and that is what I would recommend as well.
The reason why is that as soon as your template makes a reference to the computed property, this triggers your ajax call. The page will then render any other available elements, and when your ajax call returns, it will then render the data it received. No special action in code is required.
Anyway, here is what it would look like...
In your html, as an example...
<table>
<tr v-for="item in serverData">
<td>{{item.name}}</td>
<td>{{item.someOtherValue}}</td>
</tr>
</table>
export default {
name: 'pets',
data () {
return {
}
},
computed: {
serverData: function() {
// ajax call using axios - returns a json array []
axios.get("http://localhost:8080/getSomeData")
.success(function(data) {
return data;
};
}
}
}
Notice the return in the success promise returned from the ajax call - there is no need to store the data to another variable (and you should definitely not have to loop through it like the noob coder example above shows. Do that on the server, return an array ready to render - if it isn't your web service, then write your own that calls the original and do the data manipulation there).
The parts of your template that reference the computed value will render after the data arrives - there is no need to watch it.
Hope this helps!
Vue is the bomb!
<template>
<div class="panel panel-default tablecontainer">
<div class="panel-heading">ChartBookin Import</div>
<br>
<div class='col-md-12'>
<div class='col-md-3'></div>
<div class='col-md-3'>
<div class="panel panel-default">
<div class="panel-body">
<commitChart :width="150"
:height="150"></commitChart>
</div>
</div>
</div>
<div class='col-md-3'>
<div class="panel panel-default">
<div class="panel-body">
<InboxMessage :width="150"
:height="150"></InboxMessage>
</div>
</div>
</div>
</div>
<div class="panel-body">
<div class='col-md-3'>
<label> by Account </label>
<select v-model="teamId" class="form-control" rows="3">
<option VALUE="" disabled> CHOISIR UN TEAM</option>
<option v-for="option in options" v-bind:value="option.id">{{option.name}}</option>
</select>
</div>
<div class='col-md-3'>
<label> by Date</label>
<div class="form-group">
<input type="text" class="form-control" name="daterange"
value="01/01/2017-01/31/2017"/>
</div>
</div>
<div class='col-md-5'></div>
<div class='col-md-1'>
<label>Records</label>
<div class="form-group">
<select v-model="elementsPerPage" class="form-control">
<option v-for="option in filtre" v-bind:value="option">
{{ option }}
</option>
</select>
</div>
</div>
<div id="sixthTable">
<table class="table-bordered table-striped table-bordered table-hover">
<thead>
<tr>
<th v-for=" (key,value) in rows[0]" v-on:click="sortTable(value)">{{value}}
<div class="arrow" v-if="value == sortColumn"
v-bind:class="[ascending ? 'arrow_up' : 'arrow_down']"></div>
</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-if=" rows.length > 0" v-for="row in rows">
<td v-for="(key, value) in row">{{ key }}</td>
<td>
<a :href="'/stat_booking_import/' + row.Id">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
</td>
</tr>
<tr v-else> No Result Founded</tr>
</tbody>
</table>
<div class="pagination">
<div id="paginatebutton">
«
<a class="" v-for="i in num_pages()"
v-bind:class="[i == currentPage ? 'active' : '']"
v-on:click="change_page(i)">{{i}}
</a>
»
</div>
<div class="col-md-12" id="paginatetexte">
<p v-if="pages > (elementsPerPage*currentPage) ">
Showing 1 to {{elementsPerPage * currentPage }} of {{ pages }} records
</p>
<p v-else>
Showing 1 to {{pages}} of {{ pages }} records
</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import axios from 'axios';
import CommitChart from './Mail';
import InboxMessage from './Inbox';
export default {
components: {
CommitChart,
InboxMessage
},
data() {
return {
filtre: [10, 25, 50, 100],
option: 0,
options: [],
currentPage: 1,
elementsPerPage: 10,
pages: 0,
ascending: false,
sortColumn: '',
startdate: null,
enddate: null,
options: [],
teamId: null,
columns: [],
messages: [],
date: 0,
rows: {},
}
},
created() {
this.getData();
this.getTeams();
this.getMailInbox();
},
mounted() {
let vm = this;
$(document).ready(function () {
$('input[name="daterange"]').daterangepicker({
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')]
},
locale: {
format: 'YYYY-MM-DD'
},
});
$('.applyBtn').click(function () {
vm.startdate = $("input[name=daterangepicker_start]").val();
vm.enddate = $("input[name=daterangepicker_end]").val();
vm.getData();
});
$('input[name="daterange"]').on('apply.daterangepicker', function (ev, picker) {
vm.startdate = $("input[name=daterangepicker_start]").val();
vm.enddate = $("input[name=daterangepicker_end]").val();
vm.getData();
});
});
},
watch: {
date: function () {
this.getData();
},
teamId: function () {
this.getData();
},
elementsPerPage: function () {
this.getData();
}
},
methods: {
getData() {
axios.get(`/admin/stat_booking_import.json/` + this.startdate + `/` + this.teamId + `/` + this.enddate + `/` + this.elementsPerPage + `?page=` + this.currentPage)
.then(response => {
this.rows = response.data.elements.data;
this.columns = Object.keys(this.rows[0]);
this.pages = response.data.elements.total_element;
})
.catch(e => {
this.errors.push(e)
})
},
getTeams() {
axios.get('/admin/team.json')
.then(response => {
this.options = response.data.data;
this.errors = [];
})
.catch(e => {
e.message = "aucun resultat trouvé essayer de choisir une autre date";
this.errors.push(e)
})
},
getMailInbox() {
axios.get(`/mailstorage.json`)
.then(response => {
this.messages = response.data.data;
console.log(this.messages);
})
.catch(e => {
this.errors.push(e)
});
},
sortTable(col) {
if (this.sortColumn === col) {
this.ascending = !this.ascending;
} else {
this.ascending = true;
this.sortColumn = col;
}
var ascending = this.ascending;
this.rows.sort(function (a, b) {
if (a[col] > b[col]) {
return ascending ? 1 : -1
} else if (a[col] < b[col]) {
return ascending ? -1 : 1
}
return 0;
})
},
num_pages() {
return Math.ceil(this.pages / this.elementsPerPage);
},
get_rows() {
var start = (this.currentPage - 1) * this.elementsPerPage;
var end = start + this.elementsPerPage;
return this.rows.slice(start, end);
},
change_page(page) {
this.currentPage = page;
this.getData();
}
},
}
</script>
<style type="text/css">
table {
width: 100%;
}
table td {
text-align: center;
}
table td {
text-align: center;
padding: 8px;
}
table td:last-child {
border-right: none;
}
.pagination {
display: inline-block;
}
.pagination a {
color: #3097D1;
float: left;
padding: 8px 16px;
text-decoration: none;
transition: background-color .3s;
border: 1px solid #ddd;
}
.pagination a.active {
background-color: #3097D1;
color: white;
border: 1px solid #3097D1;
}
.arrow_down {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAaCAYAAABPY4eKAAAAAXNSR0IArs4c6QAAAvlJREFUSA29Vk1PGlEUHQaiiewslpUJiyYs2yb9AyRuJGm7c0VJoFXSX9A0sSZN04ULF12YEBQDhMCuSZOm1FhTiLY2Rky0QPlQBLRUsICoIN/0PCsGyox26NC3eTNn3r3n3TvnvvsE1PkwGo3yUqkkEQqFgw2Mz7lWqwng7ztN06mxsTEv8U0Aam5u7r5EInkplUol/f391wAJCc7nEAgE9Uwmkzo4OPiJMa1Wq6cFs7Ozt0H6RqlUDmJXfPIx+qrX69Ti4mIyHA5r6Wq1egND+j+IyW6QAUoul18XiUTDNHaSyGazKcZtdgk8wqhUKh9o/OMvsVgsfHJy0iWqVrcQNRUMBnd6enqc9MjISAmRP3e73T9al3XnbWNjIw2+KY1Gc3imsNHR0YV4PP5+d3e32h3K316TySQFoX2WyWR2glzIO5fLTSD6IElLNwbqnFpbWyO/96lCoai0cZjN5kfYQAYi5H34fL6cxWIZbya9iJyAhULBHAqFVlMpfsV/fHxMeb3er+Vy+VUzeduzwWC45XA4dlD/vEXvdDrj8DvURsYEWK3WF4FA4JQP9mg0WrHZbEYmnpa0NxYgPVObm5teiLABdTQT8a6vrwdRWhOcHMzMzCiXlpb2/yV6qDttMpkeshEzRk4Wo/bfoe4X9vb2amzGl+HoXNT29vZqsVi0sK1jJScG+Xx+HGkL4Tew2TPi5zUdQQt9otPpuBk3e0TaHmMDh1zS7/f780S0zX6Yni+NnBj09fUZUfvudDrNZN+GkQbl8Xi8RLRtHzsB9Hr9nfn5+SjSeWUCXC7XPq5kw53wsNogjZNohYXL2EljstvtrAL70/mVaW8Y4OidRO1/gwgbUMvcqGmcDc9aPvD1gnTeQ+0nmaInokRj0nHh+uvIiVOtVvt2a2vLv7Ky0tL3cRTXIcpPAwMDpq6R4/JXE4vFQ5FI5CN+QTaRSFCYc8vLy1l0rge4ARe5kJ/d27kYkLXoy2Jo4C7K8CZOsEBvb+9rlUp1xNXPL7v3IDwxvPD6AAAAAElFTkSuQmCC')
}
.arrow_up {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAaCAYAAACgoey0AAAAAXNSR0IArs4c6QAAAwpJREFUSA21Vt1PUmEYP4dvkQ8JFMwtBRocWAkDbiqXrUWXzU1rrTt0bdVqXbb1tbW16C9IBUSmm27cODdneoXjputa6069qwuW6IIBIdLvdaF4OAcOiGeDc87zPs/vd57P96WpFq7p6enbGo1mjKZpeTabjU1MTCRagGnOZHFxcXxtbe1XKpUq7+zslJeXl//Mz8+Hy+Uy3RxSE9qTk5M3otFooVQqgef4Wl9f343FYoEmoISrxuNxFX5f9vb2jhn/PxUKhfLS0tIPfFifUESRUMV8Pv/M6XReRm5rTGQyGeXxeGxYe1ezeBpBOBx2rKysbO7v79d4Wy3Y2Nj4GQqFbgnhaugxwiuGJx99Pp9FLBbXxYTXvTqd7v3MzIy6riIWGxJnMpl7AwMD14xGYyMsSq1WUyQdUqn0eSPlusQIsbGrq+vl4OCgvhFQZd1utyv1en0gEolcqsi47nWJlUrlG5fLZVcoFFy2nDKSDpIWlUoVTCQSEk4lCHmJMZ2GTCbTiMVikfIZ88l7enoos9l8dXt7+z6fDicxSJUokqDX6xXcl2wCROoc0vQCWL3sNfLOSdzR0fHY4XC4tVotl40gmVwup9xuN4OQv+UyqCFGH9rg7SOGYVRcBs3IEG4J0nVnamrqOtvuBDGGgQg9+wHFcVEi4a0LNkbdd6TrPKo8ODc311mteIIYjT/a398/jK+s1jnVM0kXoufCFvq0GuiIGEVgQIhfoygM1QrteEa9dAL7ITiYCt4RMabOK5AyKKzKWtvupLcRciu8D5J0EuDDPyT/Snd39yh6VtY2NhYQSR9G79Ds7OxdskRjEyAufvb7/cPoO5Z6e1+xtVKrq6vfcFzyi/A3ZrPZ3GdNSlwgo5ekE4X2RIQGf2C1WlufFE0GBeGWYQ8YERWLxQtnUVB830MKLZfL9RHir8lkssCn2G751tZWEWe03zTKm15YWPiEiXXTYDB0Ig/t7yd8PRws4EicwWHxO4jHD8/C5HiTTqd1BwcHFozKU89origB+y/kmzgYpgOBQP4fGmUiZmJ+WNgAAAAASUVORK5CYII=')
}
.arrow {
float: right;
width: 12px;
height: 15px;
background-repeat: no-repeat;
background-size: contain;
background-position-y: bottom;
}
.number {
display: inline-block;
padding: 4px 10px;
margin: 0px 5px;
cursor: pointer;
}
.number:hover,
.number.active {
background-color: #3097D1;
border-color: #3097D1;
}
#paginatetexte {
padding-top: 6%;
import Vue from 'vue'
new Vue({
el: '#statistique',
render: h => h(require('./StatBookingImport.vue'))
});
<style type="text/css">
table {
width: 100%;
}
table td {
text-align: center;
}
table td {
text-align: center;
padding: 8px;
}
table td:last-child {
border-right: none;
}
.pagination {
display: inline-block;
}
.pagination a {
color: #3097D1;
float: left;
padding: 8px 16px;
text-decoration: none;
transition: background-color .3s;
border: 1px solid #ddd;
}
.pagination a.active {
background-color: #3097D1;
color: white;
border: 1px solid #3097D1;
}
.arrow_down {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAaCAYAAABPY4eKAAAAAXNSR0IArs4c6QAAAvlJREFUSA29Vk1PGlEUHQaiiewslpUJiyYs2yb9AyRuJGm7c0VJoFXSX9A0sSZN04ULF12YEBQDhMCuSZOm1FhTiLY2Rky0QPlQBLRUsICoIN/0PCsGyox26NC3eTNn3r3n3TvnvvsE1PkwGo3yUqkkEQqFgw2Mz7lWqwng7ztN06mxsTEv8U0Aam5u7r5EInkplUol/f391wAJCc7nEAgE9Uwmkzo4OPiJMa1Wq6cFs7Ozt0H6RqlUDmJXfPIx+qrX69Ti4mIyHA5r6Wq1egND+j+IyW6QAUoul18XiUTDNHaSyGazKcZtdgk8wqhUKh9o/OMvsVgsfHJy0iWqVrcQNRUMBnd6enqc9MjISAmRP3e73T9al3XnbWNjIw2+KY1Gc3imsNHR0YV4PP5+d3e32h3K316TySQFoX2WyWR2glzIO5fLTSD6IElLNwbqnFpbWyO/96lCoai0cZjN5kfYQAYi5H34fL6cxWIZbya9iJyAhULBHAqFVlMpfsV/fHxMeb3er+Vy+VUzeduzwWC45XA4dlD/vEXvdDrj8DvURsYEWK3WF4FA4JQP9mg0WrHZbEYmnpa0NxYgPVObm5teiLABdTQT8a6vrwdRWhOcHMzMzCiXlpb2/yV6qDttMpkeshEzRk4Wo/bfoe4X9vb2amzGl+HoXNT29vZqsVi0sK1jJScG+Xx+HGkL4Tew2TPi5zUdQQt9otPpuBk3e0TaHmMDh1zS7/f780S0zX6Yni+NnBj09fUZUfvudDrNZN+GkQbl8Xi8RLRtHzsB9Hr9nfn5+SjSeWUCXC7XPq5kw53wsNogjZNohYXL2EljstvtrAL70/mVaW8Y4OidRO1/gwgbUMvcqGmcDc9aPvD1gnTeQ+0nmaInokRj0nHh+uvIiVOtVvt2a2vLv7Ky0tL3cRTXIcpPAwMDpq6R4/JXE4vFQ5FI5CN+QTaRSFCYc8vLy1l0rge4ARe5kJ/d27kYkLXoy2Jo4C7K8CZOsEBvb+9rlUp1xNXPL7v3IDwxvPD6AAAAAElFTkSuQmCC')
}
.arrow_up {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAaCAYAAACgoey0AAAAAXNSR0IArs4c6QAAAwpJREFUSA21Vt1PUmEYP4dvkQ8JFMwtBRocWAkDbiqXrUWXzU1rrTt0bdVqXbb1tbW16C9IBUSmm27cODdneoXjputa6069qwuW6IIBIdLvdaF4OAcOiGeDc87zPs/vd57P96WpFq7p6enbGo1mjKZpeTabjU1MTCRagGnOZHFxcXxtbe1XKpUq7+zslJeXl//Mz8+Hy+Uy3RxSE9qTk5M3otFooVQqgef4Wl9f343FYoEmoISrxuNxFX5f9vb2jhn/PxUKhfLS0tIPfFifUESRUMV8Pv/M6XReRm5rTGQyGeXxeGxYe1ezeBpBOBx2rKysbO7v79d4Wy3Y2Nj4GQqFbgnhaugxwiuGJx99Pp9FLBbXxYTXvTqd7v3MzIy6riIWGxJnMpl7AwMD14xGYyMsSq1WUyQdUqn0eSPlusQIsbGrq+vl4OCgvhFQZd1utyv1en0gEolcqsi47nWJlUrlG5fLZVcoFFy2nDKSDpIWlUoVTCQSEk4lCHmJMZ2GTCbTiMVikfIZ88l7enoos9l8dXt7+z6fDicxSJUokqDX6xXcl2wCROoc0vQCWL3sNfLOSdzR0fHY4XC4tVotl40gmVwup9xuN4OQv+UyqCFGH9rg7SOGYVRcBs3IEG4J0nVnamrqOtvuBDGGgQg9+wHFcVEi4a0LNkbdd6TrPKo8ODc311mteIIYjT/a398/jK+s1jnVM0kXoufCFvq0GuiIGEVgQIhfoygM1QrteEa9dAL7ITiYCt4RMabOK5AyKKzKWtvupLcRciu8D5J0EuDDPyT/Snd39yh6VtY2NhYQSR9G79Ds7OxdskRjEyAufvb7/cPoO5Z6e1+xtVKrq6vfcFzyi/A3ZrPZ3GdNSlwgo5ekE4X2RIQGf2C1WlufFE0GBeGWYQ8YERWLxQtnUVB830MKLZfL9RHir8lkssCn2G751tZWEWe03zTKm15YWPiEiXXTYDB0Ig/t7yd8PRws4EicwWHxO4jHD8/C5HiTTqd1BwcHFozKU89origB+y/kmzgYpgOBQP4fGmUiZmJ+WNgAAAAASUVORK5CYII=')
}
.arrow {
float: right;
width: 12px;
height: 15px;
background-repeat: no-repeat;
background-size: contain;
background-position-y: bottom;
}
.number {
display: inline-block;
padding: 4px 10px;
margin: 0px 5px;
cursor: pointer;
}
.number:hover,
.number.active {
background-color: #3097D1;
border-color: #3097D1;
}
#paginatetexte {
padding-top: 6%;
}
#paginatebutton {
border-radius: 1px;
}
.tablecontainer {
margin-right: 2%;
margin-left: 2%;
}
.mailinbox {
margin-left: 1%;
}
</style>
<template>
<div class="panel panel-default tablecontainer">
<div class="panel-heading">ChartBookin Import</div>
<br>
<div class='col-md-12'>
<div class='col-md-3'></div>
<div class='col-md-3'>
<div class="panel panel-default">
<div class="panel-body">
<commitChart :width="150"
:height="150"></commitChart>
</div>
</div>
</div>
<div class='col-md-3'>
<div class="panel panel-default">
<div class="panel-body">
<InboxMessage :width="150"
:height="150"></InboxMessage>
</div>
</div>
</div>
</div>
<div class="panel-body">
<div class='col-md-3'>
<label> by Account </label>
<select v-model="teamId" class="form-control" rows="3">
<option VALUE="" disabled> CHOISIR UN TEAM</option>
<option v-for="option in options" v-bind:value="option.id">{{option.name}}</option>
</select>
</div>
<div class='col-md-3'>
<label> by Date</label>
<div class="form-group">
<input type="text" class="form-control" name="daterange"
value="01/01/2017-01/31/2017"/>
</div>
</div>
<div class='col-md-5'></div>
<div class='col-md-1'>
<label>Records</label>
<div class="form-group">
<select v-model="elementsPerPage" class="form-control">
<option v-for="option in filtre" v-bind:value="option">
{{ option }}
</option>
</select>
</div>
</div>
<div id="sixthTable">
<table class="table-bordered table-striped table-bordered table-hover">
<thead>
<tr>
<th v-for=" (key,value) in rows[0]" v-on:click="sortTable(value)">{{value}}
<div class="arrow" v-if="value == sortColumn"
v-bind:class="[ascending ? 'arrow_up' : 'arrow_down']"></div>
</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-if=" rows.length > 0" v-for="row in rows">
<td v-for="(key, value) in row">{{ key }}</td>
<td>
<a :href="'/stat_booking_import/' + row.Id">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
</td>
</tr>
<tr v-else> No Result Founded</tr>
</tbody>
</table>
<div class="pagination">
<div id="paginatebutton">
«
<a class="" v-for="i in num_pages()"
v-bind:class="[i == currentPage ? 'active' : '']"
v-on:click="change_page(i)">{{i}}
</a>
»
</div>
<div class="col-md-12" id="paginatetexte">
<p v-if="pages > (elementsPerPage*currentPage) ">
Showing 1 to {{elementsPerPage * currentPage }} of {{ pages }} records
</p>
<p v-else>
Showing 1 to {{pages}} of {{ pages }} records
</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import axios from 'axios';
import CommitChart from './Mail';
import InboxMessage from './Inbox';
export default {
components: {
CommitChart,
InboxMessage
},
data() {
return {
filtre: [10, 25, 50, 100],
option: 0,
options: [],
currentPage: 1,
elementsPerPage: 10,
pages: 0,
ascending: false,
sortColumn: '',
startdate: null,
enddate: null,
options: [],
teamId: null,
columns: [],
messages: [],
date: 0,
rows: {},
}
},
created() {
this.getData();
this.getTeams();
this.getMailInbox();
},
mounted() {
let vm = this;
$(document).ready(function () {
$('input[name="daterange"]').daterangepicker({
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')]
},
locale: {
format: 'YYYY-MM-DD'
},
});
$('.applyBtn').click(function () {
vm.startdate = $("input[name=daterangepicker_start]").val();
vm.enddate = $("input[name=daterangepicker_end]").val();
vm.getData();
});
$('input[name="daterange"]').on('apply.daterangepicker', function (ev, picker) {
vm.startdate = $("input[name=daterangepicker_start]").val();
vm.enddate = $("input[name=daterangepicker_end]").val();
vm.getData();
});
});
},
watch: {
date: function () {
this.getData();
},
teamId: function () {
this.getData();
},
elementsPerPage: function () {
this.getData();
}
},
methods: {
getData() {
axios.get(`/admin/stat_booking_import.json/` + this.startdate + `/` + this.teamId + `/` + this.enddate + `/` + this.elementsPerPage + `?page=` + this.currentPage)
.then(response => {
this.rows = response.data.elements.data;
this.columns = Object.keys(this.rows[0]);
this.pages = response.data.elements.total_element;
})
.catch(e => {
this.errors.push(e)
})
},
getTeams() {
axios.get('/admin/team.json')
.then(response => {
this.options = response.data.data;
this.errors = [];
})
.catch(e => {
e.message = "aucun resultat trouvé essayer de choisir une autre date";
this.errors.push(e)
})
},
getMailInbox() {
axios.get(`/mailstorage.json`)
.then(response => {
this.messages = response.data.data;
console.log(this.messages);
})
.catch(e => {
this.errors.push(e)
});
},
sortTable(col) {
if (this.sortColumn === col) {
this.ascending = !this.ascending;
} else {
this.ascending = true;
this.sortColumn = col;
}
var ascending = this.ascending;
this.rows.sort(function (a, b) {
if (a[col] > b[col]) {
return ascending ? 1 : -1
} else if (a[col] < b[col]) {
return ascending ? -1 : 1
}
return 0;
})
},
num_pages() {
return Math.ceil(this.pages / this.elementsPerPage);
},
get_rows() {
var start = (this.currentPage - 1) * this.elementsPerPage;
var end = start + this.elementsPerPage;
return this.rows.slice(start, end);
},
change_page(page) {
this.currentPage = page;
this.getData();
}
},
}
</script>
}
#paginatebutton {
border-radius: 1px;
}
.tablecontainer {
margin-right: 2%;
margin-left: 2%;
}
.mailinbox {
margin-left: 1%;
}
</style>
You could try watch property https://v2.vuejs.org/v2/guide/computed.html#Watchers. From the doc:
While computed properties are more appropriate in most cases, there
are times when a custom watcher is necessary. That’s why Vue provides
a more generic way to react to data changes through the watch option.
This is most useful when you want to perform asynchronous or expensive
operations in response to changing data.

Table Pagination with VueJS

I want to make pagination for my table but, when I run, my data does not appear anything. I am confused my code which is wrong perhaps here anyone can help me.
var newVue = new Vue({
el: '#app',
data: {
items: [
{ name: "item #1" }, { name: "item #2" }, { name: "item #3" }, { name: "item #4" },
{ name: "item #5" }, { name: "item #6" }, { name: "item #7" }, { name: "item #8" },
{ name: "item #9" }, { name: "item #10" }, { name: "item #11" }, { name: "item #12" }
],
start: 0,
limit: 2,
pagination: null,
total: 12
},
computed: {
filtered: function(){
return this.items.slice(0, this.limit)
}
},
mounted: function() {
this.limit = parseInt(this.pagination);
},
watch: {
pagination: function() {
this.limit = parseInt(this.pagination);
if(this.limit != this.start && this.start > 0)
this.start = parseInt(this.pagination);
this.limit = this.start + parseInt(this.pagination);
}
},
methods: {
paginate: function(direction) {
if(direction === 'next') {
this.start += parseInt(this.pagination);
this.limit += parseInt(this.pagination);
}
else if(direction === 'back') {
this.limit -= parseInt(this.pagination);
this.start -= parseInt(this.pagination);
}
},
},
filters: {
paginate: function(array, start, limit) {
return array.slice(start, limit);
}
}
});
.pager button {
background: #fff;
border: 1px solid #ddd;
border-radius: 15px;
color: #337AB7;
padding: 7px 13px;
text-align: center;
}
.pager button:hover {
background: #eee;
cursor: pointer;
outline: none;
}
.pager button:disabled {
background: #eee;
color: #bbb;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.min.css" rel="stylesheet"/>
<div id="app">
<table class="table table-striped table-advance table-table-hover table-bordered">
<thead>
<th>Item</th>
</thead>
<tbody>
<tr v-for="item in filtered | paginate">
<td>{{ item.name }}</td>
</tr>
</tbody>
</table>
<div class="row">
<div class="col-md-12 center">
<ul class="pager">
<li>
<button #click="paginate('previous')" :disabled="start <= 0">
Previous
</button>
</li>
<li>
<button #click="paginate('next')" :disabled="limit >= total">
Next
</button>
</li>
</ul>
</div>
</div>
</div>
<script src="https://unpkg.com/vue#2.1.10/dist/vue.js"></script>
There are few problems with your code, after removing those your code works as can be seen here in fiiddle.
You dont need | paginate with v-for as filtered is computed property which will give you paginated result
<tbody>
<tr v-for="item in filtered | paginate">
<td>{{ item.name }}</td>
</tr>
</tbody>
in filtered you needed to pass correct params in slice method.
computed: {
filtered: function(){
return this.items.slice(this.start, this.limit)
}
},`