Попытка сделать серверную интеграцию разбивки на таблицы данных в vuejs. Но это не работает должным образом - PullRequest
0 голосов
/ 07 сентября 2018

Нужно получить. Я могу получить все элементы и страницу, но ссылки на страницы не включены. Я просто попытался сделать нумерацию страниц по шаблону по умолчанию, указанному в теме. Я думаю, что я правильно выполнил шаги, если бы он показывал totalItems больше 20 и номер страницы, но ссылка на предыдущую или следующую страницу не включается. Он просто остается выделенным как отключенный

<script>
import api from "Api";

export default {
  data() {
    return {
      loader: true,
      search: "",
      selected: [],
      headers: [
        // {
        //   text: "Dessert (100g serving)",
        //   align: "left",
        //   sortable: false,
        //   value: "name"
        // },
        { text: "Leave ID", value: "leave_id" },
        { text: "Leave Name", value: "leave_name" },
        { text: "Leave Status", value: "leave_status" }
      ],
      items: [],
      pagination:{
      	
      },
      dialog: false,
      dialogTitle: '',
      payload: {
        leave_name:"",
        leave_status:"",
        statuses: [{
          "text":"Active","value":1},
          {"text":"Inactive","value":0
        }]
      }
    };
  },
  mounted() {
    this.getLeaveDataAPI()
            .then(data => {
              console.log("datamount",data);
                this.items = data.items
                this.totalItems = data.total
            })
  },
  watch: {
        pagination: {
            handler() {
            	console.log('pagination',this.pagination);
                this.getLeaveDataAPI()
                    .then(data => {
                      console.log("datawatch",data);
                        this.items = data.items
                        this.totalItems = data.total
                    })
            },
            deep: true
        }
    },
  methods: {
    async getLeaveData() {    	
    	var take = this.pagination.rowsPerPage;
    	if(this.pagination.page >1){
    		var skip = (this.pagination.page - 1)*take;	
    	}else{
    		var skip = 0;
    	}
      api
        .get('leave?skip='+skip+'&take='+take)
        .then(response => {
          this.loader = false;
          if(response){
          	this.items = response.data.data;
          this.pagination.totalItems = response.data.total;
          console.log("items",this.items);
          }
          return response.data
        })
        .catch(error => {
          console.log(error);
        });
    },
    save() {
      console.log(this.payload);
    },
    openDialog() {
      this.dialogTitle = "Create New Leave";
      this.dialog = true;
      this.payload.leave_name = "test"
      this.payload.leave_status=1;
        // statuses: [{
        //   "text":"Active","value":1},
        //   {"text":"Inactive","value":0
        // }]
    },
    getLeaveData1() {
      return [{
                    id: 1,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 2,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 3,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 4,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 5,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 6,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 7,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 8,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 9,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 10,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 11,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 12,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 13,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 14,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 15,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                },
                {
                    id: 16,
                    leave_name: 'Frozen Yogurt',
                    leave_status: 1
                }
            ]
    },
    getLeaveDataAPI() {
        this.loading = true
        return new Promise((resolve, reject) => {
            const {
                sortBy,
                descending,
                page,
                rowsPerPage
            } = this.pagination

            let items = this.getLeaveData()
            console.log("items",items);
            if(items !=undefined){
              var total = items.total  
            }
            
            if(items !=undefined){
              if (this.pagination.sortBy) {
                items = items.sort((a, b) => {
                    const sortA = a[sortBy]
                    const sortB = b[sortBy]

                    if (descending) {
                        if (sortA < sortB) return 1
                        if (sortA > sortB) return -1
                        return 0
                    } else {
                        if (sortA < sortB) return -1
                        if (sortA > sortB) return 1
                        return 0
                    }
                })
              }

              if (rowsPerPage > 0) {
                  items = items.slice((page - 1) * rowsPerPage, page * rowsPerPage)
              }

              setTimeout(() => {
                  this.loading = false
                  resolve({
                      items,
                      total
                  })
              }, 0)
            }
            
        })
    }
  }
};
</script>

	
		
		
		
      Open Dialog
			
				
				
					
						
							{{ props.header.text }}
						
						
							{{ props.header.text }}
						
					
				
				
					
						
					
					{{ props.item.id }}
					{{ props.item.leave_name }}
					InactiveActive
				
				
        {{pagination}}
</ Приложение-карта> </ V-контейнер> {{dialogTitle}} </ v-card-title> <! - <v-card-text> Разрешить приложениям Google определять местоположение. Это означает отправку анонимных данных о местоположении в Google, даже если приложения не запущены. </ V-card-text> -> <обтекание строки v-layout> </ v-text-field> </ V-флекс> </ v-select> </ V-флекс> </ V-макет> </ V-формы> </ v-распорка> Не согласен </ v-btn> Согласен </ v-btn> </ V-карты-акции> </ V-карта> </ V-диалог>

1 Ответ

0 голосов
/ 07 сентября 2018

Я столкнулся с той же проблемой. В итоге мне пришлось создать функциональность нумерации страниц с помощью функции ASYNC.

Все комментируется.

Я объявляю в this.page.filters.page текущую страницу. Он просматривает $ route.query для параметра 'page' (www.example.com/location?page=2). Если его нет, по умолчанию он равен 1.

Также объявите пустой объект this.page.paginator.

Когда компонент создается, он проверяет, содержит ли $ route.query параметр 'page', а если нет, устанавливает его.

Нам нужно вычислить номер текущей страницы и значение страницы. Смотрите «paginate ()» и «pagenum ()» в разделе «вычисленные» свойства.

Тогда нам нужно следить за значением 'pagenum' для любых изменений.

В функции 'getVideosByCategory ()' мы должны сделать несколько проверок и добавить новый уровень истории в браузер пользователей, чтобы они могли использовать кнопку "Назад" при переключении страниц. Мы также должны убедиться, что пользователь не пытается выйти за пределы последней страницы, а затем отправить их обратно на последнюю страницу, если они это сделают.

Наконец, функция async paginator (). Сначала мы проверяем, не меньше ли оно 5. Это число можно изменить в зависимости от вашего макета и количества страниц, которые вы хотите показать. Затем следует закомментированная логика, чтобы отобразить номера страниц и вставить их в объект this.page.paginator.

Затем в шаблоне я моделирую div из 'paginate' и использую элементы router-link для генерации ссылок на страницы. Первая проверяет, находится ли она на странице больше 1, и, если да, отображает активную ссылку «Предыдущая», в противном случае - неактивную. Затем он перебирает все страницы в объекте 'paginate' и создает ссылку на каждую страницу. Во время этого он проверяет номер текущей страницы и деактивирует ссылку для текущей страницы.

Используемая SCSS превращает элемент .paginator в элемент flex-box и отображает элементы в строке с равным интервалом.

<script>
import TestService from '@/services/TestService';
import _ from 'lodash';

export default {
  name: 'videos',
  data() {
    return {
      videos: [],
      page: {
        data: [],
        ippOptions: {
          4: 4,
          6: 6,
          8: 8,
          10: 10,
          12: 12,
          14: 14,
          18: 18,
        },
        filters: {
          // Check to see if an Items Per Page setting was set in the URL
          // If not, default to 12 items per page
          ipp: (this.$route.query.hasOwnProperty('ipp'))?this.$route.query.ipp:12,
          page: (this.$route.query.hasOwnProperty('page'))?this.$route.query.page:1,
          product: (this.$route.query.hasOwnProperty('product'))?this.$route.query.product:0,
        },
        paginator: [],
      },
    };
  },
  created() {
    // When the component is created, check to see if there is an Items Per Page
    // setting or a page number in the URL, if not, default those $route parameters
    // manually as follows.
    if (!('ipp' in this.$route.query)) {
      // Set the $route Items per Page to the this.page.filters.ipp value
      this.$route.query.ipp = this.page.filters.ipp;
    }
    if (!('page' in this.$route.query)) {
      // Default to page 1, if page is not defined, then it is the first page of results
      this.$route.query.page = 1;
    }
    if (!('product' in this.$route.query)) {
      // Default to page 1, if page is not defined, then it is the first page of results
      this.$route.query.product = 0;
    }
  },
  mounted() {
    // Get the category/name from the end of the path
    const type = this.$route.params.category;
    // Set Video Type Attributes
    const types = {
      products: {
        id: 'products',
        name: 'Corporate Products',
      },
      android: {
        id: 'android',
        name: 'Android',
      },
      ios: {
        id: 'ios',
        name: 'iOS',
      },
      windows: {
        id: 'windows',
        name: 'Windows',
      },
      'cross-device': {
        id: 'cross-device',
        name: 'Cross-Device',
      },
      'processes-and-tools': {
        id: 'Processes and Tools',
        name: 'Processes and Tools',
      },
      all: {
        id: 'all',
        name: 'All Videos',
      },
    };
    // Check if the supplied value is in the allowed values
    if (type in types) {
      // Put the Page information into a DOM accessible array
      this.page.data = types[type];
      // If they need all Videos, call getRecentVideos
      if (type === 'all') {
        this.getRecentVideos(this.page.filters.ipp, this.$route.query.page, this.page.filters.product);
      } else {
        // Gets the videos by category (type) and amount
        this.getVideosByCategory(this.page.data.id, this.page.filters.ipp, this.$route.query.page, this.page.filters.product);
      }
    } else {
      // If it's not a valid category, send an error 404 message
      window.location = 'https://clpstaging.mcafee.com/error';
    }
  },
  watch: {
    // Watch for the Items Per Page selection to change
    ipp(val) {
      // If they need all Videos, call getRecentVideos
      if (this.page.data.id === 'all') {
        this.getRecentVideos(val, this.$route.query.page, this.page.filters.product);
      } else {
        // Reload the component
        this.$route.query.ipp = val;
        this.getVideosByCategory(this.page.data.id, val, this.$route.query.page, this.page.filters.product);
      }
    },
    // Watch for changes to the page number
    pagenum(val) {
      // If they need all Videos, call getRecentVideos
      if (this.page.data.id === 'all') {
        this.getRecentVideos(this.page.filters.ipp, val, this.page.filters.product);
      } else {
        // Reload the component
        this.$route.query.page = val;
        this.getVideosByCategory(this.page.data.id, this.$route.query.ipp, val, this.page.filters.product);
      }
    },
    // Watch for changes to the product filter
    productFilter(val) {
      // If they need all Videos, call getRecentVideos
      if (this.page.data.id === 'all') {
        this.getRecentVideos(this.page.filters.ipp, this.$route.query.page, val);
      } else {
        // Reload the component
        this.$route.query.product = val;
        this.getVideosByCategory(this.page.data.id, this.$route.query.ipp, this.$route.query.page, val);
      }
    }
  },
  computed: {
    // Define the function that chunks the results to build a
    // responsive layout.
    videoChunks() {
      return _.chunk(this.videos, 2);
    },
    // Define the Items-Per-Page value for the Watcher
    // This ensures the data is updated when a user makes a change
    // to Items-Per-Page filter.
    ipp() {
      return this.page.filters.ipp;
    },
    // Define the paginator value
    paginate() {
      return this.page.paginator;
    },
    // Define the pagenum value for the Watcher.
    // This ensures that the component is reloaded
    // when the users makes a selection from the paginator.
    pagenum() {
      return (this.$route.query.page === 'undefined')?1:this.$route.query.page;
    },
    productFilter() {
      return this.page.filters.product;
    },
  },
  methods: {
    // Methods that get called upon mount. See Vue component lifecycle.
    async getVideosByCategory(category, amount, pagenumber, productId) {
      // Build filters
      await this.getProducts();
      // Wait for the API to send back a response. await keyword only works in async functions
      const response = await TestService.fetchVideosByCategory(category, amount, pagenumber, productId);
      // Total number of results
      this.page.data.total = response.data[1][0].total;
      // Set total number of pages based on Items per Page
      this.page.data.pages = Math.ceil(response.data[1][0].total / this.page.filters.ipp);
      // Set the videos object to the first object (the array of videos we want)
      // of the JSON response from the API
      this.videos = response.data[0];
      // Add a new level of history without reloading the page with the udpated filters
      // And set the props to match
      // If the current url in the address bar is different from the query that
      // would generate the data on the page
      if (`${this.$route.path}?ipp=${amount}&page=${pagenumber}&product=${productId}` != this.$route.fullPath) {
        history.pushState(this.page, 'Example Site', `${this.$route.path}?ipp=${amount}&page=${pagenumber}&product=${productId}`);
        this.$route.query.page = pagenumber;
        this.page.filters.page = pagenumber;
        this.$route.query.ipp = amount;
        this.page.filters.ipp = amount;
        this.$route.query.product = productId;
        this.page.filters.product = productId;
      }
      // Add a new level of history without reloading the page with the udpated filters
      // And set the props to match
      // If the selected filters result in no results found
      if (this.page.data.pages === 0) {
        history.pushState(this.page, 'Example Site', `${this.$route.path}?ipp=${amount}&page=1&product=${productId}`);
        this.$route.query.page = 1;
        this.page.filters.page = 1;
        this.$route.query.ipp = amount;
        this.page.filters.ipp = amount;
        this.$route.query.product = productId;
        this.page.filters.product = productId;
      }
      // Check to make sure that the user isn't beyond the last page of results.
      // If they are, redirect them to the last page of results.
      // When updating filters, it's possible for a user to set a filter while on page 10,
      // But the results would only fill 7 pages. The user would be redirected to page 7 with
      // the same filters.
      if (this.page.data.pages < this.$route.query.page && this.page.data.pages != 0) {
        let redir = '';
        for (const key in this.page.filters) {
          redir = `${redir}&${key}=${this.page.filters[key]}`;
        }
        redir = redir.replace(/^&/g, '?').replace(/page=[0-9]*/g, `page=${this.page.data.pages}`);
        window.location = redir;
      }
      // build paginator
      await this.paginator(this.page.data.total, this.page.data.pages, this.$route.query.page);
    },
    async getRecentVideos(amount, pagenumber, productId) {
      // Build filters
      await this.getProducts();
      // Wait for the API to send back a response. await keyword only works in async functions
      const response = await TestService.fetchVideos(amount, pagenumber, productId);
      // Total number of results
      this.page.data.total = response.data[1][0].total;
      // Set total number of pages based on Items per Page
      this.page.data.pages = Math.ceil(response.data[1][0].total / this.page.filters.ipp);
      // Set the videos object to the first object (the array of videos we want)
      // of the JSON response from the API
      this.videos = response.data[0];
      // Add a new level of history without reloading the page with the udpated filters
      // And set the props to match
      // If the current url in the address bar is different from the query that
      // would generate the data on the page
      if (`${this.$route.path}?ipp=${amount}&page=${pagenumber}&product=${productId}` != this.$route.fullPath) {
        history.pushState(this.page, 'Example Site', `${this.$route.path}?ipp=${amount}&page=${pagenumber}&product=${productId}`);
        this.$route.query.page = pagenumber;
        this.page.filters.page = pagenumber;
        this.$route.query.ipp = amount;
        this.page.filters.ipp = amount;
        this.$route.query.product = productId;
        this.page.filters.product = productId;
      }
      // Add a new level of history without reloading the page with the udpated filters
      // And set the props to match
      // If the selected filters result in no results found
      if (this.page.data.pages === 0) {
        history.pushState(this.page, 'Example Site', `${this.$route.path}?ipp=${amount}&page=1&product=${productId}`);
        this.$route.query.page = 1;
        this.page.filters.page = 1;
        this.$route.query.ipp = amount;
        this.page.filters.ipp = amount;
        this.$route.query.product = productId;
        this.page.filters.product = productId;
      }
      // Check to make sure that the user isn't beyond the last page of results.
      // If they are, redirect them to the last page of results.
      // When updating filters, it's possible for a user to set a filter while on page 10,
      // But the results would only fill 7 pages. The user would be redirected to page 7 with
      // the same filters.
      if (this.page.data.pages < this.$route.query.page && this.page.data.pages != 0) {
        let redir = '';
        for (const key in this.page.filters) {
          redir = `${redir}&${key}=${this.page.filters[key]}`;
        }
        redir = redir.replace(/^&/g, '?').replace(/page=[0-9]* /g, `page=${this.page.data.pages}`);
        window.location = redir;
      }
      // build paginator
      await this.paginator(this.page.data.total, this.page.data.pages, this.$route.query.page);
    },
    async getProducts() {
      // Fetch the list of products
      const response = await TestService.fetchProducts();
      // Set the response to a variable
      let out = response.data;
      // Unshift the array and add a default "All" products option to the top
      out.unshift({product_name: 'All',tid: 0,});
      this.page.data.products = out;
    },
    async paginator(total, pages, thisPage) {
      // Find out where to start the Paginator at.
      // Set the start variable
      var start = 0;
      if (Number(thisPage) <= 5) {
        // If the user is looking at page 5 or less, start the count at 1
        start = 1;
      } else {
        // If the user is looking at a page higher than 5, check to see if the
        // user is on a page 5 or less away from the last page.
        if (Number(thisPage)+5 > pages) {
          // If the current page is 5 or less away from the last page,
          // we need to make sure that the navigation stays visually similar
          // by making sure that the same number of pages remain in the paginator.
          // Do this by the following equation where:
          // c = current page Number
          // t = total number of pages
          // c - ( 10 - ( t - c ) )
          start = Number(thisPage)-(10-(pages-Number(thisPage)));
        } else {
          // If the current page is more than 5 away from the last page,
          // just start at 5 before the current page.
          start = Number(thisPage)-5;
        }
      }
      // set the end variable
      var end = 0;
      // Check if the current page is 5 or less away from the last page.
      if (Number(thisPage)+5 > pages) {
        // If the current page number is 5 or less away from the last page,
        // set it to to the number of the last page.
        end = pages;
      } else {
        // If the current page is more than 5 away from the last page,
        // check to see if the current page is 5 or less away from the
        // first page.
        if (Number(thisPage) <= 5) {
          // If the current page is 5 away or closer to the first page,
          // we need to make sure that the navigation stays visually similar
          // by making sure that the same number of pages remain in the paginator.
          // Do this by the following equation where:
          // c = current page Number
          // c + ( 10 - c )
          end = Number(thisPage)+(11-Number(thisPage));
        } else {
          // If the current page is more than 5 away from the first page,
          // end 5 after current page. It's already been checked that
          // the current page is more than 5 away from the last page.
          end = Number(thisPage)+5;
        }
      }
      // Set an array to hold the page numbers
      var pageArr = [];
      // Count the line numbers and push them into the array
      for (var count = start; count <= end; count++) {
        pageArr.push(count);
      }
      // Set the paginator numbers into the DOM
      this.page.paginator = pageArr;
    },
  },
};
</script>
<style lang="scss">
@import '../assets/scss/_colors.scss';

.paginator {
  div {
    list-style-type:none;
    padding:0rem;
    display:flex;
    flex-flow:nowrap;
    justify-content:space-around;
    .router-link-active {
      display:inline-block;
      width:100%;
      color:$darkGray;
      padding: 0.5rem 0rem;
      border-top:solid $lightGray 0.2rem;
      font-size: 1.6rem;
      font-weight:bold;
      text-decoration:none;
      &.disabled {
        color: $lightGray;
        &:hover {
          border-top: solid $lightGray 0.2rem;
          cursor:default;
        }
      }
      &.router-link-exact-active {
        border-top:solid $mcafeeRed 0.2rem;
      }
      &:hover {
        border-top:solid $mcafeeRed 0.2rem;
      }
    }
  }
}
</style>
<template>
  <b-container>
    <b-row class="w-100">
      <b-col md="12" lg="12" xl="12" class="paginator">
        <div v-model="paginate">
          <router-link
            v-if="$route.query.page > 1"
            :to="{ name: $route.name, query: { ipp: page.filters.ipp, page: Number($route.query.page) - 1, product: page.filters.product} }"
            class="prev">&lt;&nbsp;&nbsp;&nbsp;Previous</router-link>
          <div
            v-else
            class="prev disabled router-link-active">&lt;&nbsp;&nbsp;&nbsp;Previous</div>
          <router-link v-for="pages in paginate"
            v-bind:key = "pages"
            :to="{ name: $route.name, query: { ipp: page.filters.ipp, page: pages, product: page.filters.product} }">{{ pages }}</router-link>
          <router-link
            v-if="page.data.pages > $route.query.page"
            :to="{ name: $route.name, query: { ipp: page.filters.ipp, page: Number($route.query.page) + 1, product: page.filters.product} }"
            class="next">Next&nbsp;&nbsp;&nbsp;&gt;</router-link>
          <div
            v-else
            class="next disabled router-link-active">Next&nbsp;&nbsp;&nbsp;&gt;</div>
        </div>
      </b-col>
    </b-row>
  </b-container>
</template>
...