UiPagination.vue 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <template>
  2. <div class="flex items-center">
  3. <ui-button
  4. v-tooltip="t('components.pagination.prevPage')"
  5. :disabled="modelValue <= 1"
  6. icon
  7. @click="updatePage(modelValue - 1)"
  8. >
  9. <v-remixicon name="riArrowLeftSLine" />
  10. </ui-button>
  11. <div class="mx-4">
  12. <input
  13. ref="inputEl"
  14. v-tooltip="t('components.pagination.currentPage')"
  15. :value="modelValue"
  16. :max="maxPage"
  17. min="0"
  18. class="
  19. p-2
  20. text-center
  21. transition
  22. w-10
  23. appearance-none
  24. bg-input
  25. rounded-lg
  26. "
  27. type="number"
  28. @click="$event.target.select()"
  29. @input="updatePage(+$event.target.value, $event.target)"
  30. />
  31. {{ t('components.pagination.of', { page: maxPage }) }}
  32. </div>
  33. <ui-button
  34. v-tooltip="t('components.pagination.nextPage')"
  35. :disabled="modelValue >= maxPage"
  36. icon
  37. @click="updatePage(modelValue + 1)"
  38. >
  39. <v-remixicon rotate="180" name="riArrowLeftSLine" />
  40. </ui-button>
  41. </div>
  42. </template>
  43. <script setup>
  44. import { computed, ref, watch } from 'vue';
  45. import { useI18n } from 'vue-i18n';
  46. const props = defineProps({
  47. modelValue: {
  48. type: Number,
  49. default: 1,
  50. },
  51. records: {
  52. type: Number,
  53. default: 10,
  54. },
  55. perPage: {
  56. type: Number,
  57. default: 10,
  58. },
  59. });
  60. const emit = defineEmits(['update:modelValue', 'paginate']);
  61. const { t } = useI18n();
  62. const inputEl = ref(null);
  63. const maxPage = computed(() => Math.round(props.records / props.perPage));
  64. function emitEvent(page) {
  65. emit('update:modelValue', page);
  66. emit('paginate', page);
  67. }
  68. function updatePage(page, element) {
  69. let currentPage = page;
  70. if (currentPage > maxPage.value || currentPage < 1) {
  71. if (!element) return;
  72. currentPage = currentPage > maxPage.value ? maxPage.value : 1;
  73. }
  74. emitEvent(currentPage);
  75. }
  76. watch(
  77. () => [props.perPage, props.records],
  78. () => {
  79. emitEvent(1);
  80. }
  81. );
  82. </script>
  83. <style scoped>
  84. input::-webkit-outer-spin-button,
  85. input::-webkit-inner-spin-button {
  86. -webkit-appearance: none;
  87. margin: 0;
  88. }
  89. input[type='number'] {
  90. -moz-appearance: textfield;
  91. }
  92. </style>