I am working on a small application that displays a “users” JSON in an HTML5 table. I use Twitter Bootstrap 3, Axios and Vue.js 2 for this purpose.
The code I have so far:
var app = new Vue({
el: '#app',
data: {
users: [],
loading: true,
errored: false,
url: "https://randomuser.me/api/?&results=100&inc=name,location,email,cell,picture",
page: 1,
perPage: 10,
pages: [],
},
methods: {
getUsers() {
axios
.get(this.url)
.then(response => {
this.users = response.data.results
})
.catch(error => {
console.log(error)
this.errored = true
})
.finally(() => this.loading = false)
},
setPages() {
var numberOfPages = Math.ceil(this.users.length / this.perPage);
for (var index = 1; index <= numberOfPages; index++) {
this.pages.push(index);
}
},
paginate(users) {
var page = this.page;
var perPage = this.perPage;
var from = (page * perPage) - perPage;
var to = (page * perPage);
return users.slice(from, to);
}
},
created() {
this.getUsers();
},
watch: {
users() {
this.setPages();
}
},
computed: {
displayedUsers() {
return this.paginate(this.users);
}
},
filters: {
lowercase(value) {
return value.toLowerCase();
},
capitalize(value) {
return value.charAt(0).toUpperCase() + value.slice(1);
}
}
});
.table-container {
margin: 10px;
}
.table-container .panel-heading {
font-weight: bold;
}
.table-container .panel-body {
padding: 0;
}
.table-container table {
margin-bottom: 0;
border: none;
}
.table-container table tr:last-child td {
border-bottom: none;
}
.table-container table tr th {
font-weight: bold;
}
.table-container table tr th:first-child, .table-container table tr td:first-child {
border-left: none;
}
.table-container table tr th:last-child, .table-container table tr td:last-child {
border-right: none;
}
.table-container table tr td {
padding: 2px 8px !important;
vertical-align: middle;
}
.table-container table tr td .picture {
padding-right: 10px;
}
.table-container table tr td img {
max-height: 30px;
width: auto;
border: 1px solid #c7c7c7;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div id="app" class="container">
<div class="panel panel-default table-container">
<div class="panel-heading">Users</div>
<div class="panel-body">
<div class="table-responsive">
<table class="table table-striped table-bordered" id="dataTable">
<thead>
<tr>
<th class="text-right">#</th>
<th>Name</th>
<th>Email</th>
<th>City</th>
</tr>
</thead>
<tbody>
<tr v-for="(user, index) in displayedUsers">
<td class="text-right">{{perPage * (page - 1) + index + 1}}</td>
<td>
<span class="picture">
<img :src="user.picture.thumbnail" :alt="user.name.first + ' ' + user.name.last" class="img-circle">
</span>
<span>{{user.name.first | capitalize}} {{user.name.last | capitalize}}</span>
</td>
<td><a :href="'mailto:' + user.email | lowercase">{{user.email | lowercase}}</a></td>
<td>{{user.location.city | capitalize}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<nav class="text-center" aria-label="Page navigation">
<ul class="pagination pagination-sm">
<li>
<a href="#" @click="page = 1" aria-label="First">
<span aria-hidden="true">«</span>
</a>
</li>
<li>
<a href="#" v-if="page != 1" @click="page--" aria-label="Previous">
<span aria-hidden="true">‹</span>
</a>
</li>
<li v-for="pageNumber in pages.slice(page-1, page+4)"><a href="#" @click="page = pageNumber">{{pageNumber}}</a></li>
<li>
<a href="#" @click="page++" v-if="page < pages.length" aria-label="Next">
<span aria-hidden="true">›</span>
</a>
</li>
<li>
<a href="#" @click="page = pages.length" aria-label="Last">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>
I have paginated the results (10 per page). The problem is, I got stuck adding the class active to the current page item: <li class="active"><a href="#">2</a></li>
.
How can I achieve that?
2
Answers
adding
:class="{'active': page === pageNumber}
to the page items iteration code worked:Like this (quick example):
or
Hope, I understood your question.