Pagination in vue.js framework - vue.js

Error with Pagination in vue.js framework in view page, The Pagination bar is working fine but I have 50 records on the same page. The Pagination bar is 17 => 50/3 . The Post is displayed in div section not in Table.
<template>
<div class="blog">
<h2>{{ pageDescreption }}</h2>
<hr />
<div class="alert alert-success" role="alert" v-text="alertTitel"></div>
<div class="row">
<div class="col-md-8">
<div class="posts-area">
<PostList
id="PostList"
v-for="post in posts"
:key="post.id"
:post="post"
:current-page="currentPage"
:per-page="perPage"
/>
<div class="overflow-auto">
<b-pagination
v-model="currentPage"
:total-rows="rows"
:per-page="perPage"
aria-controls="PostList"
></b-pagination>
<p class="mt-3">Current Page: {{ currentPage }}</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import PostList from "#/components/Blogs/PostList.vue";
import PostJson from "../Gatewaye/post.json";
export default {
data: function() {
return {
pageName: "blog",
pageDescreption: "This is an Blog page",
alertTitel: "List of all Posts",
posts: PostJson, // array of posts [50 records]
perPage: 3,
currentPage: 1
};
},
name: "Blog",
components: {
PostList
},
computed: {
rows() {
return this.posts.length;
}
}
};
</script>
And in Components file Blog.vue is:
<template>
<div class="PostList">
<div class="post-container text-left">
<span class="post-views badge badge-primary" title="Views">{{
post.views
}}</span>
<h3 class="post-title" title="Title">{{ post.title }}</h3>
<span class="post-date" title="Date">{{ post.date }}</span>
<p class="post-body">
{{ post.contant }}
</p>
<div class="row">
<div class="col-sm-6">
<span class="post-author" title="Auther">{{ post.auther }}</span>
</div>
<div class="col-sm-6 text-right">
<span class="post-category" title="Category">{{
post.category
}}</span>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ["post"],
name: "PostList"
};
</script>
The Pagination bar is working fine but I have 50 records on the same page ... Thank you

Use a computed property to slice the post array in the parent component:
computed: {
paginatedposts() {
return this.posts.slice(this.perPage*(this.currentPage-1), (this.perPage*(this.currentPage-1))+this.perPage);
}
}
Now you just need to bind this computed property:
<PostList
id="PostList"
v-for="post in paginatedposts"
:key="post.id"
:post="post"
/>

Related

How to toggle between components when onclick function happens on a icon in vue.js?

I have four components Dashboard.vue(parent component) it contains Three child components(DisplayBooks.vue,sortBooksHightoLow,sortBooksLowtoHigh).
Now i want to import one more component called Cart.vue inside the Dashboard.vue .By default only DisplayBooks.vue component is only visible,if i click on cart-icon inside the Dashboard component it displays the Cart.vue component and hides the DisplayBooks.vue component .
How to acheive this thing please help me to fix this thing..
Dashboard.vue
<template>
<div class="main">
<div class="navbar navbar-default navbar-fixed-top">
<div class="navbar-header">
<img src="../assets/education.png" alt="notFound" class="education-image" />
</div>
<ul class="nav navbar-nav">
<li>
<p class="brand">Bookstore</p>
</li>
</ul>
<div class="input-group">
<i #click="handlesubmit();" class="fas fa-search"></i>
<div class="form-outline">
<input type="search" v-model="name" class="form-control" placeholder='search...' />
</div>
</div>
<ul class="nav navbar-nav navbar-right" id="right-bar">
<li><a> <i class="far fa-user"></i></a></li>
<p class="profile-content">profile</p>
<li><a><i class="fas fa-cart-plus"></i></a></li>
<p class="cart-content" >cart <span class="length" v-if="booksCount">{{booksCount}}</span></p>
</ul>
</div>
<div class="mid-body">
<h6>Books<span class="items">(128items)</span></h6>
<select class="options" #change="applyOption">
<option disabled value="">Sort by relevance</option>
<option value="HighToLow">price:High to Low</option>
<option value="LowToHigh">price:Low to High</option>
</select>
</div>
<div v-if="flam==false">
<h2>Hello</h2>
</div>
<DisplayBooks v-show="flag==='noOrder'" #update-books-count="(n)=>booksCount=n"/>
<sortBooksLowtoHigh v-show="flag==='lowToHigh'" />
<sortBooksHightoLow v-show="flag==='highToLow'" />
<Cart />
</div>
</template>
<script>
import sortBooksLowtoHigh from './sortBooksLowtoHigh.vue'
import sortBooksHightoLow from './sortBooksHightoLow.vue'
import DisplayBooks from './DisplayBooks.vue'
import Cart from './Cart.vue'
export default {
components: {
DisplayBooks,
sortBooksLowtoHigh,
sortBooksHightoLow,
Cart
},
data() {
return {
booksCount:0,
flag: 'noOrder',
brand: 'Bookstore',
name: '',
flam: true,
visible: true,
}
},
methods: {
flip() {
this.flam = !this.flam;
},
applyOption(evt) {
if (evt.target.value === "HighToLow") {
this.flag = 'highToLow';
} else this.flag = 'lowToHigh';
},
}
}
</script>
Cart.vue
<template>
<div class="main">
<div v-for="book in books" :key="book.id" class="container">
<div class="content">
<h5>My Cart({{booksCount}})</h5>
</div>
<div class="mid-section">
<img v-bind:src="book.file" alt="not found">
<p class="title-section">{{book.name}}</p>
</div>
<div class="author-section">
<p>by {{book.author}}</p>
</div>
<div class="price-section">
<h6>Rs.{{book.price}}</h6>
</div>
<button class="close-btn" #click="handlesubmit();" type="submit">close</button>
<div class="btn-grps">
<button class="btn" type="submit" >Place Order</button>
</div>
</div>
</div>
</template>
<script>
import service from '../service/User'
export default{
data(){
return {
booksCount:0,
books: [{
id: 0,
file: 'https://images-na.ssl-images-amazon.com/images/I/41MdP5Tn0wL._SX258_BO1,204,203,200_.jpg',
name: 'Dont Make me think',
author: 'Sai',
price: '1500'
},]
}
},
methods:{
}
}
</script>
It's recommended to use vur-router, but for a simple situation you could define a property called shownComp then update when you click on cart icon :
data() {
return {
shownComp:'DisplayBooks',
booksCount:0,
flag: 'noOrder',
then <li #click="shownComp='Cart'"><a><i class="fas fa-cart-plus"></i></a></li>
and :
<DisplayBooks v-show="flag==='noOrder' && shownComp==='DisplayBooks'" #update-books-count="(n)=>booksCount=n"/>
<Cart v-show=" shownComp==='Cart'" />
...

Accessing Vuex data within dynamic _id.vue page - Vue/Nuxt

I want to access my user details stored in the state when visiting a dynamic (_id.vue) page. I have set the id of the page like this after using the link to the page:
data() {
return {
selectedTutor: null,
id: this.$route.params.id,
}
},
But now I need to define the selectedTutor by searching the id within the data in the vuex state. I was trying to do something like this:
created() {
this.selectedTutor = this.$store.state.tutors.find((tutor) => tutor.id === this.id)
},
But everything stays undefined. So when id equals to the id within the object, that object needs to be set as selectedTutor so I can access all the necessary data to be displayed on the page.
Here you can see the Vuex state
EDIT
_id.vue page
<template>
<div>
<section>
<div>
<h3>
{{ id }}
</h3>
</div>
</section>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'TutorPage',
/* eslint-disable vue/require-prop-types */
layout: 'app',
props: ['id'],
middleware: 'auth',
data() {
return {
selectedTutor: null,
}
},
computed: {
...mapState(['tutors']),
},
created() {
this.selectedTutor = this.$store.state.tutors.find(
(tutor) => tutor.id === this.id
)
},
}
</script>
MainResult Page
<base-grid>
<ul id="tutors" class="grid grid-cols-2 gap-6">
<tutor-item
v-for="tutor in tutors"
:id="tutor.id"
:key="tutor.id"
:name="tutor.attributes.name"
:rate="student.hourlyRate"
:subject="student.subject"
:description="student.biography"
:profile-image="student.imageUrl"
:image-alt="student.imageAlt"
:age="student.age"
:rating="student.rating"
:total-reviews="student.reviewCount"
class="overflow-hidden bg-white border rounded-lg shadow-md"
>
</tutor-item>
</ul>
</base-grid>
Tutor Item (the resultcard)
<template>
<div>
<li>
<div class="flex">
<div class="w-2/3">
<img
class="flex-shrink-0 object-cover w-full h-64 mx-auto bg-gray-200"
:src="profileImage"
:alt="imageAlt"
/>
</div>
<div class="p-6">
<div
class="text-xs font-semibold leading-snug tracking-wide text-gray-500 uppercase"
>
{{ subject }} • {{ age }} jaar
</div>
<NuxtLink :to="'/tutors/' + id">
<h4 class="text-lg font-semibold leading-5 tracking-wide">
{{ name }}
</h4>
</NuxtLink>
<div class="mt-2">
{{ rate }}€
<span class="text-sm text-gray-600">per uur</span>
</div>
<div class="mt-2">
<span class="font-semibold text-light-blue-800"
>{{ rating }}/5 sterren</span
>
<span class="text-sm text-gray-600 truncate">
(na {{ totalReviews }} reviews)
</span>
</div>
<div class="mt-2">{{ description }}</div>
<div>
<div class="mt-4 text-sm font-semibold text-gray-600">
<span>MA</span>
<span
class="inline-block leading-7 text-center text-gray-100 bg-yellow-400 bg-opacity-50 w-7 h-7 rounded-xl"
>DI</span
>
<span>WO</span>
<span
class="inline-block leading-7 text-center text-gray-100 bg-yellow-400 bg-opacity-50 w-7 h-7 rounded-xl"
>DO</span
>
<span
class="inline-block leading-7 text-center text-gray-100 bg-yellow-400 bg-opacity-50 w-7 h-7 rounded-xl"
>VR</span
>
<span>ZA</span>
<span>ZO</span>
</div>
</div>
</div>
</div>
</li>
</div>
</template>
<script>
export default {
/* eslint-disable vue/require-prop-types */
name: 'TutorItem',
props: [
'id',
'firstName',
'lastName',
'name',
'rate',
'subject',
'age',
'rating',
'totalReviews',
'description',
'profileImage',
'imageAlt',
],
computed: {
fullName() {
return this.firstName + ' ' + this.lastName
},
tutorsDetailsLink() {
return this.$route.path + '/' + this.id
},
},
}
</script>
<style></style>
EDIT
Whoops, what a mistake. It was returning the id as a string but I needed a number. This is why it returned undefined. It is solved now! Thanks

Data not updating when API changed on Vue Js

Ok, I have a problem, here I make a data post with a tag, and when I click the tag the other data posts are not updated by the tag.
i'm get the api with created function, Do I have to use vuex?
can everyone help me, thanks very much
this is my template
<div class="col-md-4 mb-4" v-for="post in posts" :key="post.id">
<div class="card h-100 shadow-sm border-0 rounded-lg">
<div class="card-img">
<img :src="path+'/storage/posts/'+post.image" class="w-100"
style="height: 200px;object-fit: cover;border-top-left-radius: .3rem;border-top-right-radius: .3rem;">
</div>
<div class="card-body">
<router-link :to="{name: 'detail_post', params: {slug: post.slug}}"
class="text-dark text-decoration-none">
<h6>{{ post.title }}</h6>
</router-link>
</div>
<div class="card-footer bg-white">
<i class="fa fa-calendar" aria-hidden="true"></i> {{ post.created_at }}
</div>
</div>
</div>
this is my JavaScript
<script>
//import axios
import axios from 'axios'
export default {
name: 'PostIndex',
data() {
return {
path: axios.defaults.baseURL,
posts: []
}
},
created() {
//get post homepage
axios.get(`/api/tag/${this.$route.params.slug}`).then(response => {
this.posts = response.data.data.data;
})
}
}
</script>

Passing events between Vue parent and child

I am trying to emit an event from a child and listen for it on the parent, but I am always getting errors like Invalid handler for event "new-tab": got undefined.
My app:
<div class="ibox" id="app">
<div class="ibox-content">
<h2>Table</h2>
<div class="details">
<table-tabs
v-on:new-tab="newTab"
v-on:close-tab="closeTab"
ref="tableTabs"
name="table-tabs"
></table-tabs>
</div>
</div>
</div>
TableTabs component:
<template>
<div>
<b-card no-body>
<b-tabs card>
<b-tab active>
<template slot="title">
<i class="fa fa-tablet-alt"></i> Orders
</template>
<orders-table
name="orders-table"
></orders-table>
</b-tab>
<b-tab v-for="order in tabs" :key="i">
<template slot="title">
<div>{{ order.name }}</div>
<b-button type="button" class="close float-right" aria-label="Close" #click="closeTab(order.id)">
<span aria-hidden="true">×</span>
</b-button>
</template>
<items-table
name="items-table"
:api-url="'/api/items/' + order.id"
></items-table>
</b-tab>
</b-tabs>
</b-card>
</div>
</template>
<script>
export default {
name: 'table-tabs',
data() {
return {
tabs: [],
}
},
methods: {
closeTab(id) {
for (let i = 0; i < this.tabs.length; i++) {
if (this.tabs[i].id === id) {
this.tabs.splice(i, 1);
}
}
},
newTab(item) {
this.tabs.push(item);
}
}
}
</script>
OrdersTable component:
<template>
<div>
<vuetable ref="vuetable"
:api-url="apiUrl"
:fields="fields"
pagination-path="pagination"
#vuetable:pagination-data="onPaginationData"
>
<div slot="name-slot" slot-scope="{ rowData }">
<a href="#" class="float-left" #click="newTab(rowData.order)">
{{ rowData.order.name }}
<span class="fa fa-search-plus"></span>
</a>
</div>
</vuetable>
<div class="row">
<div class="col-md-6">
<vuetable-pagination-info
ref="paginationInfo"
></vuetable-pagination-info>
</div>
<div class="col-md-6">
<vuetable-pagination-bootstrap
ref="pagination"
class="pull-right"
#vuetable-pagination:change-page="onChangePage"
></vuetable-pagination-bootstrap>
</div>
</div>
</div>
</template>
<script>
import Vuetable from 'vuetable-2/src/components/Vuetable';
import VuetablePaginationBootstrap from '../VuetablePaginationBootstrap';
import VuetablePaginationInfo from 'vuetable-2/src/components/VuetablePaginationInfo';
import TableFieldDef from './table-field-def';
export default {
name: 'orders-table',
components: {
Vuetable,
VuetablePaginationBootstrap,
VuetablePaginationInfo
},
data() {
return {
apiUrl: '/api/orders?include=items',
fields: TableFieldDef,
}
},
methods: {
newTab(order) {
this.$emit('new-tab', order);
}
}
}
</script>
Why does this.$emit('new-tab', order) always result in the handler newTab being undefined.
Vue 2.5.21
The parent in this case is the TableTabs component. If the parent needs to listen to events emitted by a child component then it needs to add the event listener to the child component, which is the OrdersTable component in this case. So instead of this ..
<table-tabs
v-on:new-tab="newTab"
v-on:close-tab="closeTab"
ref="tableTabs"
name="table-tabs"
></table-tabs>
You should do this (inside the TableTabs component) ..
<orders-table
name="orders-table"
v-on:new-tab="newTab"
></orders-table>

[Vue warn]: Error in render: “TypeError: Cannot read property ‘name’ of undefined”

I get the error
TypeError: Cannot read property ‘name’ of undefined”
if I go to deep in the object.
Timeline.vue
<template>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="card card-default">
<div class="card-header">Timeline</div>
<div class="card-body">
<post v-for="post in posts" :key="post.id"></post>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Post from './Post.vue'
export default {
data () {
return {
posts: []
}
},
components: {
Post
},
mounted() {
this.$http.get('/posts').then((response) => {
console.log(response.body)
this.posts =response.body
})
}
}
</script>
post.vue
<template>
<div class="media">
<div class="media-left">
</div>
<div class="media-body">
<strong>test</strong>
<strong>{{ post.user.name }} </strong>
</div>
</div>
</template>
<script>
export default {
props: [
'post'
]
}
</script>
Then why I get the error?
I suppose some problem with {{ post.user.name }}.
You need to pass the post prop in the template like so. otherwise it's undefined in the child component (post).
<div class="card-body">
<post
v-for="post in posts"
:key="post.id"
:post="post">
</post>
</div>