Search code examples
vuejs2vue-componentv-forcomputed-properties

Pass Vue js search filter functionality through single file components with EventBus


I have the following components:

/components/SearchBlogs.vue Search component to filter on blog.title and blog.description.

/components/BlogList.vue Here I list all the Blog items.

SearchBlogs.vue

<template>
  <div>
    <input type="text" v-model="search" @change="emitSearchValue" placeholder="search blog">
  </div>
</template>

<script>
import { EventBus } from '../event-bus.js'

export default {
  name: 'SearchBlogs',
  data: () => {
    return {
      search: ''
    }
  },
  methods: {
    emitSearchValue() {
      EventBus.$emit('search-value', 'this.search')
    }
  }
}
</script>

BlogList.vue

<template>
<div>
  <div v-for="blog in filteredBlogs" :key="blog">
    <BlogListItem :blog="blog" /> 
  </div>
</div>
</template>

<script>
import BlogListItem from './BlogListItem'
import { EventBus } from '../event-bus.js'

export default {
  name: 'BlogList',
  components: {
    BlogListItem,
  },
  data: () => {
    return {
      blogs: [],
      searchvalue: ''
    }
  },
  computed: {
    filteredBlogs() {
      return this.blogs.filter(blog =>
        blog.name.toLowerCase().includes(
          this.searchvalue.toLowerCase()
        )
      )
    }
  },
  created() {
    fetch('http://localhost:3000/blogs')
    .then(response => {
      return response.json();
    })
    .then(data => {
      this.blogs = data;
    }),
    EventBus.$on('search-value', (search) => {
      this.searchvalue = value;
    })
  }
}
</script>

In another page component Blogs I register both components:

<template>
  <div>
    <h1>Blog</h1>
    <TheSidebar>
      <SearchBlogs />
    </TheSidebar>
    <BlogList/>
  </div>
</template>

Can anybody see what's missing here? I want, as soon as the user types something in the search input (from the SearchBlogs.vue component), it start filtering and updating the list.


Solution

  • Look at my solution condesandbox

    Here is an explanation: You don't need to use EventBus. You can communicate with Search Component by v-model, using prop value and emiting updated value from the Input.

    Then your Main (List) Component is responsible for all the logic.

    1. It keeps the state of a Search
    2. It keeps the items and filtered Items

    Thanks to that your Search Component is very clear and has no data, that means it has very little responsibility.

    Please ask questions if I can add something to help you understand 😉

    UPDATE:

    1. EventBus is a great addition in some cases. Your case is simple enough, there is no need to add it. Right now your architecture is "over engineered".
    2. When you have added listener on EventBus, on created:hookyou should always remove it while Component is being destroyed. Otherwise you can encounter a trouble with double calling function etc. This is very hard to debug, tryst me I'he been there 😉
    3. Going with my suggestion gives you comfort of "no-need-to-remember-about-this" because Vue is doing it for you.

    Hope that help.