how to add filters and search in tables in vuejs? - filter

I am learning vue js and building a SPA i want to know how do I add filters and search using an input tag. I also want to add a feature that when i click on a particular name on the table it should open the profile of that person also a select all functionality
<template>
<div class="animated fadeIn">
<input type="text" placeholder="Enter Name" v-model="searchText">
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>College Name</th>
<th>College City</th>
<th>Level Name</th>
<th>Submitted</th>
<th>Pending</th>
<th>Completed</th>
<th>Approved</th>
<th>Rejected</th>
</tr>
</thead>
<tbody>
<tr v-for="profile in profilesdata">
<td>{{profile.first_name}}</td>
<td>{{profile.college_name}}</td>
<td>{{profile.college_city}}</td>
<td>{{profile.level_name}}</td>
<td>{{profile.submitted}}</td>
<td>{{profile.pending}}</td>
<td>{{profile.complete}}</td>
<td>{{profile.approve}}</td>
<td>{{profile.rejected}}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default{
name: 'profiles',
data () {
return{
profilesdata: []
}
},
created:function(){
this.loadlike()
},
methods:{
loadlike:function(){
this.$http.get('/api/profiles').then(function (res) {
this.profilesdata = res.body
console.log(53+this.profiles)
})}}}
</script>

you could probably return computed list instead of profilesData
<template>
...
<input type="text" placeholder="Enter Name" v-model="searchText">
...
<tr v-for="profile in computedProfilesData">
...
</template>
<script>
export default{
...
data () {
return {
...
// - you need info for searchText
searchText: ''
}
}
...
computed: {
computedProfilesData(){
let searchString = this.searchText;
return this.profilesdata.filter((profile) => {
// example
profile.first_name.indexOf(searchString) !== -1;
})
}
}
</script>
there is a lot of different ways to do this, this is just one of them.
you can pass that searchString to API and return result list, it all comes to that
what do you really need.

You can make a computed for the filtered data:
computed: {
filteredProfiles() {
return this.profilesdata.filter(profile => {
// TODO filter profile with this.searchText
})
}
}
And then change the v-for to loop over the filtered data: <tr v-for="profile in filteredProfiles">

Related

Vue3 + DataTables redraw the table after delete

I have a Vue3 component that renders tables based on model data. Then I add DataTables functionality to the table to be able to filter and sorting data. Everything works fine. But if I click on the delete button I need to send a delete ajax request to the server and then on success redraw the whole table with new data. I tried to use draw() method but it does not work. Deleted rows are still in the table. I don't know if I need to remove the whole table and create it again or there is another solution.
This is the Vue template code.
<template>
<div class="table-responsive">
<table :id="id" class="table table-bordered nowrap" width="100%;">
<thead>
<tr>
<th>id</th>
<th>Title</th>
<th>Visible</th>
<th>User</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="article in articles" :key="article.id">
<td>{{article.id}}</td>
<td>{{article.title}}</td>
<td>{{article.visible}}</td>
<td>{{article.user.name}}</td>
<td>
delete
</td>
</tr>
</tbody>
</table>
</div>
</template>
And this is the deleteArticle() code
deleteArticle(id) {
axios.get( apiRoutes.ARTICLE_DELETE_URL + id )
.then( response => {
this.getArticles();
})
.catch( response => {
console.log(response);
});
},
getArticles()
{
axios.get( apiRoutes.ARTICLES_URL )
.then((response) => {
this.articles = response.data.articles;
this.$nextTick(function() {
this.setDataTable();
});
})
.catch((response) => {
console.log(response);
});
},
setDataTable() {
var table = $('#'+this.id);
if( this.dataTableObject )
{
this.dataTableObject.reload().draw(); // This is the code I need to fix
return;
}
...
},
What is the right flow of this component?

How to pass a vue data value or id from a href link to load new component to show this value or id?

I have one vue componet i wanna click to a href link bellow code to load another vue componet to pass id or any value of this form.
<template>
<div class="container">
<table class="table table-hover">
<tbody>
<tr>
<th>No</th>
<th>another vue component</th>
</tr>
<tr>
<td>1 </td>
<td>
<a href="'/NewVueComponent.vue/ + this.form.id'" > show </a>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data (){
return {
form: new Form({
id: '',
})
}
}
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
In your view component, have a method that will push router to another view. The id can be passed as an arg via params.
<script>
export default: {
data() {
return {
id: "someId"
}
},
methods: {
goTo() {
this.$router.push({name: OtherComponent, params: {
id: this.id
}})
}
}
}
</script>
and on your route declaration, make sure props is set to true
{
path: "/path-to-component",
component: OtherComponent,
name: "OtherComponent",
props: true,
}
and of course on the OtherComponent you will have to define id as a prop.
You can read more about it here https://router.vuejs.org/guide/essentials/passing-props.html

Data are not loaded in Edit Form in Vue app

I'm experimenting with Vue.js and Axios with Laravel. I'm using this tutorial where a simple Posts app is build: https://pusher.com/tutorials/laravel-vue-axios. I'm trying to extend this with an Update function. When I'm clicking on the edit button near a Post, the right Id is fetched. But in my Edit form the data of the post aren't loading. What could be the issue?
This is my code in EditPost.vue:
<template>
<form action="" #submit="editPost(post)">
<h4 class="text-center font-weight-bold">Post edit form</h4>
<div class="form-group">
<input type="text" placeholder="title" class="form-control"> {{ post.title }}
</div>
<div class="form-group">
<textarea placeholder="content" class="form-control" v-model="post.content">
</textarea>
</div>
<div class="form-group">
<button :disabled="!isValid" class="btn btn-block btn-primary" #click.prevent="updatePost(post)">Update
</button>
</div>
</form>
</template>
<script>
import {mapGetters, mapActions} from 'vuex'
export default {
name: "EditPost",
data() {
return {
post:{}
}
},
created () {
this.fetchData();
},
mounted() {
this.$store.dispatch('fetchPost')
},
methods: {
...mapActions('post', [
'fetchPost',
'updatePost'
]),
updatePost(post) {
this.$store.dispatch('updatePost', post)
},
fetchData: function () {
var _this = this;
// ajax call - then
_this.$store.commit('setData', {
name: 'post',
data: res.data.post
});
}
},
computed: mapGetters([
'posts'
])
}
</script>
This is the code in recources/js/store/actions.js:
fetchPost({commit}, post) {
axios.get(`/api/posts/${post.id}`)
.then(res => {
commit('FETCH_POST', res.data)
}).catch(err => {
console.log(err)
})
},
UPDATE: I've put in extra code.
file Posts.vue:
<template>
<div>
<h4 class="text-center font-weight-bold">Posts</h4>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Content</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="post in posts">
<td>{{post.title}}</td>
<td>{{post.content}}</td>
<td>
<button class="btn btn-info" #click="editPost(post)"><i style="color:white" class="fa fa-edit"></i></button>
<button class="btn btn-danger" #click="deletePost(post)"><i style="color:white" class="fa fa-trash"></i></button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
name: "Posts",
mounted() {
this.$store.dispatch('fetchPosts')
},
methods: {
editPost(post) {
this.$store.dispatch('fetchPost',post)
},
deletePost(post) {
this.$store.dispatch('deletePost',post)
}
},
computed: {
...mapGetters([
'posts'
])
}
}
</script>
file recources/js/store/getters.js:
let getters = {
posts: state => {
return state.posts
}
}
export default getters
file recources/js/store/state.js:
let state = {
posts: []
}
export default state
file recources/js/store/mutations.js:
let mutations = {
CREATE_POST(state, post) {
state.posts.unshift(post)
},
FETCH_POSTS(state, posts) {
return state.posts = posts
},
UPDATE_POST(state, post) {
let index = state.posts.findIndex(item => item.id === post.id)
},
DELETE_POST(state, post) {
let index = state.posts.findIndex(item => item.id === post.id)
state.posts.splice(index, 1)
}
}
export default mutations
You are using post.content, which is coming from your data prop post. I don't see you adding content to post anywhere in your code.
I'm assuming your getter posts is getting the post data from the store.
So maybe you just need to use that instead?
v-model="posts.content">
Without seeing more of your code I cannot tell you exactly what to do. But your main problem is after you update the store value you need to get that value somehow.

Is there a way to update my component dynamically without refreshing the page?

I have a vue component which builds the card up, and within that component is another component that I pass data to with a prop I currently use Swal to as a popup to add a new project to the database however when it finishes adding I have to refresh the page for the data to be visible. The entire reason I wanted to use vue was to not have to refresh the page to view updated data and I haven't been able to figure it out.
This is my Projects.vue
import ProjectItem from './Projects/ProjectItem.vue';
export default {
name: "Projects",
components: {
ProjectItem
},
data() {
return {
projects: []
}
},
methods: {
getProjects () {
axios.get('/api/projects').then((res) => {this.projects = res.data});
},
addProject() {
Swal.queue([{
title: 'Add a New Project?',
html:
'<label for="name" style="color: #000;font-weight: 700">Project Name<input id="name" class="swal2-input"></label>' +
'<label for="description" style="color: #000;font-weight: 700">Project Description<textarea id="description" rows="5" cols="15" class="swal2-input"></textarea></label>',
showCancelButton: true,
confirmButtonText: 'Create Project',
showLoaderOnConfirm: true,
preConfirm: (result) => {
return new Promise(function(resolve, reject) {
if (result) {
let name = $('#name').val();
let desc = $('#description').val();
axios.post('/api/projects', {title:name,description:desc})
.then(function(response){
Swal.insertQueueStep({
type: 'success',
title: 'Your project has been created!'
})
resolve();
})
.catch(function(error){
Swal.insertQueueStep({
type: 'error',
title: 'Something went wrong.'
})
console.log(error);
reject();
})
}
});
}
}])
}
},
mounted () {
this.getProjects();
}
I bind it to ProjectItem in my Project.vue template:
<div class="table-responsive border-top">
<table class="table card-table table-striped table-vcenter text-nowrap">
<thead>
<tr>
<th>Id</th>
<th>Project Name</th>
<th>Team</th>
<th>Date</th>
<th>Preview</th>
</tr>
</thead>
<project-item v-bind:projects="projects" />
</table>
and this is my ProjectItem.vue:
<template>
<tbody>
<tr v-for="project in projects" :key="project.id">
<td>{{ project.id }}</td>
<td>{{ project.title }}</td>
<td><div class="avatar-list avatar-list-stacked">
{{ project.description }}
</div>
</td>
<td class="text-nowrap">{{ project.updated_at }}</td>
<td class="w-1"><i class="fa fa-eye"></i></td>
</tr>
</tbody>
</template>
<script>
export default {
name: "ProjectItem",
props: ["projects"],
}
</script>
You must insert the recently added project to the products array.
If you are able to change the backend code, you could change the response to include the project.
this.projects.push(response.project);

Checkbox doesn't save true value

I'm using Laravel 5.6 and Vuejs 2.
If I click on my checkbox and make the value true it's supposed to save a 1 in the database and if I click my checkbox and make the value false it saves a 0.
The problem I'm having is that if I click my checkbox and make it true, it doesn't save the correct value, no changes is made to the database and I don't get any errors. If I click on my checkbox and make it false, it saves the 0 correctly.
I did notice that even when my value is supposed to be true, I do get a false when I dd($category->has('active')
I'm not sure where I'm going wrong or how to fix it.
My vue file
<template>
<div class="card-body">
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Active</th>
<th scope="col">Title</th>
<th scope="col">Edit</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
<tr v-for="(category, index) in categoriesNew" >
<td>
<label>checkbox 1</label>
<input name="active" type="checkbox" v-model="category.active" #click="checkboxToggle(category.id)">
</td>
<td>
{{ category.title }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
props: ['categories'],
data(){
return {
categoriesNew: this.categories
}
},
methods: {
checkboxToggle(id){
console.log(id);
axios.put('/admin/category/active/'+id, {
categories: this.categoriesNew
}).then((response) => {
//Create success flash message
})
},
},
mounted() {
console.log('Component mounted.')
}
}
</script>
my routes
Route::put('admin/products/updateAll', 'Admin\ProductsController#updateAll')->name('admin.products.updateAll');
Route::put('admin/category/active/{id}', 'Admin\CategoryController#makeActive')->name('admin.category.active');
Route::resource('admin/category', 'Admin\CategoryController');
Route::resource('admin/products', 'Admin\ProductsController');
my CategoryController#makeActive
public function makeActive(Request $request, $id)
{
$category = Category::findOrFail($id);
if($request->has('active'))
{
$category->active = 1;
}else{
$category->active = 0;
}
$category->save();
}
I hope I made sense. If there is anything that isn't clear or if you need me to provide more info, please let me know
Try changing this line
categories: this.categoriesNew
to
categories: category.active
and add a data prop at the top called category.active: ''
I've managed to get it to work. This is what I did.
vue file
<template>
<div class="card-body">
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Active</th>
<th scope="col">Title</th>
<th scope="col">Edit</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
<tr v-for="(category, index) in categories" >
<td>
<label>checkbox 1</label>
<input type="checkbox" v-model="category.active" #click="checkboxToggle(category)">
</td>
<td>
{{ category.title }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
props: ['attributes'],
data(){
return {
categories: this.attributes,
}
},
methods: {
checkboxToggle (category) {
axios.put(`/admin/category/${category.id}/active`, {
active: !category.active
}).then((response) => {
console.log(response)
})
}
},
mounted() {
console.log('Component mounted.')
}
}
</script>
my routes
Route::put('admin/category/{category}/active', 'Admin\CategoryController#makeActive')->name('admin.category.active');
and my CategoryController#makeActive
public function makeActive(Request $request, $id)
{
$category = Category::findOrFail($id);
if(request('active') === true)
{
$category->active = 1;
}else{
$category->active = 0;
}
$category->save();
}

Resources