Laravel: Filtered List with Blade & Vue
Build a reactive filtered list with Blade & Vue
Prepare your blade template
@bot // static contant goes here...@else <div id="filter"></div>@endbot
The Vue-App
Your app consists of two files, the entry-point post-filter/index.js
:
import Vue from 'vue';import VueRouter from 'vue-router';Vue.use(VueRouter);const App = { template: '<div id="filter"><router-view /></div>' };const router = new VueRouter({ mode: 'history', routes: [ { path: '/filter/:categories?', name: 'filter', component: () => import('./Filter'), props(route) { const categories = route.params.categories?.toString() || null; return { categories: categories ? categories.split(',') : [], }; }, }, ],});const app = new Vue({ render: (h) => h(App), router,}).$mount('#filter');
and the post-filter/Filter.vue
:
<template> <div> <label> <input type="checkbox" value="1" v-model="categories" /> Category 1 </label> <label> <input type="checkbox" value="2" v-model="categories" /> Category 2 </label> <transition-group name="list-complete" class="flex flex-row flex-wrap w-full list-complete" tag="section" > <div v-for="post in posts" :key="post.id" class="w-1/3 p-5 transition-transform duration-200" > <h3 class="text-xl">{{ post.title }}</h3> {{ post.body }} </div> </transition-group> </div></template><script>export default { name: 'PostFilter', props: { /** * We get an array with categories from the router. * It is a representation of the categories from the route param. */ categories: { type: Array, }, }, data() { return { posts: [], }; }, /** * The mounted hook will only get called once. * A route change of the vue router will not affect this hook. */ mounted() { this.getPosts(); }, watch: { /** * Whenever the list of categories changes, we need to redirect * with the new route params. */ sortedCategories(val) { // make a string from the sorted array [1,2] => '1,2' // or set to null if empty let categories = this.sortedCategories.join(',') || null; // check if the params differ to prevent double route hits if (this.$route.params.categories != categories) { // go to filter route with new params this.$router.push({ name: 'filter', params: { categories, }, }); // fetch a filtered set of posts this.getPosts(); } }, }, methods: { async getPosts() { this.posts = await axios.post('/api/enpoint', { query: this.sortedCategories, }); }, }, computed: { sortedCategories() { return this.categories.sort(); }, },};</script><style scoped>.list-complete-enter,.list-complete-leave-to { opacity: 0; transform: translateY(0px);}.list-complete-leave-active { position: absolute;}</style>