Search app with Lunr

by Jay Angelo Valmocina

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lunr.js/2.3.5/lunr.min.js"></script>
<div id="app">
  <mysearchbtn inline-template :search.sync="search">
    <div>
      <input type="text" placeholder="type to search" v-model="search" @input="$emit('update:search', $event.target.value)" />
    </div>
  </mysearchbtn>
  <p>Number of results: <b>{{list.length}}</b></p>
  <mylist inline-template :list="list">
    <ul>
      <li v-for="item in list" :key="item.id">{{item.name}}</li>
    </ul>
  </mylist>
</div>

CSS

* {
  font-family: Helvetica;
}

input {
  border: none;
  padding: 14px;
  font-size: 16px;
  box-shadow: 0px 2px 2px lightgrey;
}

ul li {
  font-size: 15px;
  list-style-type: none;
  padding: 15px;
  margin-bottom: 10px;
  box-shadow: 0px 2px 2px lightgrey;
}

JavaScript

Vue.component('mysearchbtn', {
  props: ['search']
})


Vue.component('mylist', {

  props: ['list']
})


new Vue({
  el: '#app',
  data() {
    return {
      original: [],
      list: [],
      search: '',
      resuls: [],
      searchIndex: null
    }
  },
  mounted() {
    axios('https://jsonplaceholder.typicode.com/comments')
      .then(data => {
        this.original = data.data
        this.list = this.original
        this.buildIndex()
      })

    this.$watch('search', () => {
      this.resuls = this.searchIndex.search(this.search)

      this.list = []
      this.resuls.forEach(d => {
        this.original.forEach(p => {
          if (d.ref == p.id) this.list.push(p)
        })

      })
    })
  },
  methods: {
    buildIndex() {
      var documents = this.original
      this.searchIndex = lunr(function() {
        this.ref('id')
        this.field('name')
        this.field('body')
        this.field('email')

        documents.forEach(doc => {
          this.add(doc)
        })
      })
    }
  }
})