adam78
adam78

Reputation: 10068

Vue.js - Pagination

I have the following pagination component.

If users adds remove items dynamically i.e via some ajax call, how do i ensure the correct active or disabled classes are applied on the pagination links?

For example if the user is currently on the last page which only has 1 item, if the user deletes that item, the pagination links re-render but then i lose the active disable class becuase that page no longer exists. i.e. the links should update to move the user to previous page.

 <div class="comment-pager ">
    <div class="panel panel-default panel-highlight no-border ">
        <div class="panel-body padded-5">
            <nav v-if="totalItems > pageSize">
                <ul class="pagination">
                    <li v-bind:class="[currentPage == 1 ? disabled : '']">
                        <a v-on:click.prevent="previous()" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                        </a>
                    </li>
                    <li v-bind:class="[currentPage == pages ? active : '']" v-for="page in pages" v-on:click.prevent="changePage(page)">
                        <a>{{ page }}</a>
                    </li>
                    <li v-bind:class="[currentPage == pages.length ? disabled : '']">
                        <a v-on:click.prevent="next()" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                        </a>
                    </li>
                </ul>
            </nav>  
        </div>
   </div>
</div>     


</template>

<script>

export default {

    props: ['totalItems', 'pageSize']

    data: function () {

        return {
            currentPage: 1,
            pages: [],
        }

    },

    watch: {
        totalItems: function () {

           var pagesCount = Math.ceil(this.totalItems / this.pageSize); 
           this.pages = [];
           for (var i = 1; i <= pagesCount; i++)
            this.pages.push(i);  
        }
    },

    methods: {

        changePage: function (page){

            this.currentPage = page; 
            this.$emit('pageChanged', page);
        }

        previous: function (){
            if (this.currentPage == 1)
                return;

            this.currentPage--;

            this.$emit('pageChanged', this.currentPage);
        }

        next: function () {
            if (this.currentPage == this.pages.length)
                return; 

            this.currentPage++;

            this.$emit('pageChanged', this.currentPage);
        }
    },

}


</script>

  <paginator v-bind:total-items="totalItems" v-bind:page-size="query.pageSize" v-on:pageChanged="onPageChange"></paginator>

Upvotes: 2

Views: 2970

Answers (2)

klimat
klimat

Reputation: 24991

You probably want to use watch property of a Vue instance.

 var vm = new Vue({
  data: {
    count: 1
  },
  watch: {
    count: function (val, oldVal) {
      console.log('new: %s, old: %s', val, oldVal)
    }
})

Upvotes: 0

Vamsi Krishna
Vamsi Krishna

Reputation: 31362

There is no complete equivalent to ngOnChanges() in vue.

ngOnChanges() is a lifecycle hook which takes in an object that maps each changed property name to a SimpleChange object holding the current and previous property values.

If you want the lifecycle hook that gets invoked after every change in data and before re-rendering the virtual DOM then you should be using beforeUpdate() hook.

But as in ngOnChanges() you can't get the hold of which property is updated or what is it's oldvalue or newValue is.

As mklimek answered you can set up watcher on the properties you want to watch for changes.

In watcher you get what the oldValue is and what it's changed new value is

new Vue({
    el:'#app',
    data:{
        prop1: '',
        prop2: '' // property to watch changes for
    },
    watch:{
        prop@(newValue, oldValue){
            console.log(newValue);
            console.log(oldValue);
        }
    }
});

EDIT

For your case you do not need a watcher. You can setup the pages[] property as a computed property:

computed:{
    pages(){
        var pageArray = [];
        var pagesCount = Math.ceil(this.totalItems / this.pageSize); 
        
        for (var i = 1; i <= pagesCount; i++)
            pages.push(i);
        }
        return pageArray;
}

computed properties are cached based on their dependencies. A computed property will only re-evaluate when some of its dependencies have changed in your case the props totalItems and pageSize

Now you can use the pages computed property as normal data property

Upvotes: 2

Related Questions