skip to Main Content

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">&laquo;</span>
        </a>
      </li>
      <li>
        <a href="#" v-if="page != 1" @click="page--" aria-label="Previous">
          <span aria-hidden="true">&lsaquo;</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">&rsaquo;</span>
        </a>
      </li>
      <li>
        <a href="#" @click="page = pages.length" aria-label="Last">
          <span aria-hidden="true">&raquo;</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


  1. Chosen as BEST ANSWER

    adding :class="{'active': page === pageNumber} to the page items iteration code worked:

    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">&laquo;</span>
            </a>
          </li>
          <li>
            <a href="#" v-if="page != 1" @click="page--" aria-label="Previous">
              <span aria-hidden="true">&lsaquo;</span>
            </a>
          </li>
          <li v-for="pageNumber in pages.slice(page-1, page+4)" :class="{'active': page === pageNumber}"><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">&rsaquo;</span>
            </a>
          </li>
          <li>
            <a href="#" @click="page = pages.length" aria-label="Last">
              <span aria-hidden="true">&raquo;</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>


  2. Like this (quick example):

     <li :class="{'active': page === 1}">...</li>
    

    or

     <li :class="{'active': page === pages.length}">...</li>
    

    Hope, I understood your question.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search