Reputation: 381
I'm using Laravel and VueJs,
I'm trying the following: I 've created a search bar to find users by their names, last name or email.
I used computed to write my filter but I've realized that my filter only filters over the 10 first elements (because I'm using paginate to show all users stored in my database)
...what can I do to make my filter works over all my users instead each ten that gives me paginate (if it's possible keeping paginate, please)?
This is my script and template (thank you very much):
<script>
import UpdateProfile from './users/UpdateProfile';
import CreateUser from './users/CreateUser';
import User from '../models/user';
export default {
components: {UpdateProfile, CreateUser},
data() {
return {
showUpdateModal: false,
showCreateModal: false,
users: [],
user: new User(),
search:'',
paginator: {
current: 1,
total: 1,
limit: 10,
}
}
},
mounted() {
this.goToPage(1);
},
methods: {
userPermissions(user) {
return this.CONSTANTS.getUserType(user.permissions);
},
addUser(user) {
this.showCreateModal = false;
this.api.post('/users', user).then(() => {
this.goToPage(this.paginator.current);
});
},
editUser(user) {
this.user = JSON.parse(JSON.stringify(user));
this.showUpdateModal = true;
},
updateUser(user) {
this.showUpdateModal = false;
this.api.put('/users/' + user.id, user).then(() => {
this.goToPage(this.paginator.current)
});
},
deleteUser(user) {
this.api.delete('/users/' + user.id).then(() => {
this.goToPage(this.paginator.current)
});
},
navigatePrev(page) {
this.goToPage(page)
},
navigateNext(page) {
this.goToPage(page)
},
goToPage(page) {
this.api.get('/users?page=' + page + '&limit=' + this.paginator.limit).then(response => {
this.users = response.data;
this.paginator = response.paginator;
});
}
},
computed:{
filteredUsers: function () {
return this.users.filter((user) => {
var searchByName = user.name.toLowerCase().match(this.search.toLowerCase());
var searchByLastName = user.lastname.toLowerCase().match(this.search.toLowerCase());
var searchByEmail = user.email.toLowerCase().match(this.search.toLowerCase());
if(searchByName){
return searchByName;
}
if(searchByLastName){
return searchByLastName;
}
if(searchByEmail){
return searchByEmail;
}
});
}
}
}
</script>
<template>
<div class="container">
<div class="button is-primary" @click="showCreateModal=true" v-if="CONSTANTS.hasRootPermissions()">
<span class="icon"><i class="fas fa-plus fa-lg"></i></span>
<span>Add User</span>
</div>
<br><br>
<create-user v-if="CONSTANTS.hasRootPermissions()"
:show="showCreateModal"
v-on:save="addUser"
v-on:close="showCreateModal=false"/>
<!--Search Users-->
<div class="control is-expanded">
<h1>Search users</h1>
<input class="input" type="text" v-model="search" placeholder="Find a user"/>
</div>
<br><br>
<!--Search Users-->
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Admin</th>
<th>Permissions</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="user in filteredUsers">
<td>{{user.name}}</td>
<td>{{user.lastname}}</td>
<td>{{user.email}}</td>
<td>{{user.isAdmin ? 'yes' : 'no'}}</td>
<td>{{userPermissions(user)}}</td>
<td>
<div class="button is-info" @click="editUser(user)">
<span class="icon"><i class="far fa-edit"></i></span>
<span>Edit</span>
</div>
</td>
<td>
<div class="button is-danger" @click="deleteUser(user)">
<span class="icon"><i class="far fa-trash-alt"></i></span>
<span>Delete</span>
</div>
</td>
</tr>
</tbody>
</table>
<paginator :paginator="paginator" v-on:prev="navigatePrev" v-on:next="navigateNext"/>
<update-profile :data="user" :show="showUpdateModal" v-on:save="updateUser" v-on:close="showUpdateModal=false"/>
</div>
</template>
Upvotes: 2
Views: 1998
Reputation: 550
You can get all your users (if that's not too much data) at start and then paginate them on a clientside.
Something like:
mounted() {
this.api.get('/users').then(response => {
this.users = response.data;
this.paginator.total = Math.ceil(this.users.length / this.paginator.limit);
});
},
methods: {
goToPage(page) {
this.paginator.current = page;
}
},
computed:{
filteredUsers: function () {
return this.users.filter((user) => {
var searchByName = user.name.toLowerCase().match(this.search.toLowerCase());
var searchByLastName = user.lastname.toLowerCase().match(this.search.toLowerCase());
var searchByEmail = user.email.toLowerCase().match(this.search.toLowerCase());
if(searchByName){
return searchByName;
}
if(searchByLastName){
return searchByLastName;
}
if(searchByEmail){
return searchByEmail;
}
}).filter((el, index) => {
return ( index >= (this.paginator.current - 1) * this.paginator.limit
&& index < this.paginator.current * this.paginator.limit);
});
}
}
}
Update
Other option would be to perform serching on a serverside and to send a search string with every page request:
methods: {
goToPage(page) {
this.api.get('/users?page=' + page + '&limit=' + this.paginator.limit
+ '&search=' + this.search).then(response => {
this.users = response.data;
this.paginator = response.paginator;
});
},
performSearch() {
this.goToPage(1);
},
},
}
with search block in a template:
<!--Search Users-->
<div class="control is-expanded">
<h1>Search users</h1>
<input class="input" type="text"
v-model="search" placeholder="Find a user"
@change="performSearch"/>
</div>
You can add debouncing to get results after you type or add a "search!" button after your search input field to trigger performSearch()
.
<!--Search Users-->
<div class="control is-expanded">
<h1>Search users</h1>
<input class="input" type="text"
v-model="search" placeholder="Find a user"/>
<button @click="performSearch">Search!</button>
</div>
Upvotes: 1