Overview using a Vuetify.js components - Auto Complete

by Anurak Sumranphan

HTML

<script src="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/Sortable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.20.0/vuedraggable.umd.min.js"></script>
<div id="app">
  <v-app>
    <v-autocomplete
      v-model="values"
      :items="items"
      :loading="isLoading"
      :search-input.sync="search"
      label="Public APIs"
      placeholder="Search..."
      item-text="Description"
      item-value="API"
      color="white"
      hide-no-data
      hide-selected
      chips
      multiple
      outlined
      dark
    >
      <template v-slot:selection="data">
        <v-chip
          v-bind="data.attrs"
          :input-value="data.selected"
          draggable
          close
          @click="data.select"
          @click:close="removeItem(data.item)"
        >
          {{ data.item.Description }}
        </v-chip>
      </template>
    </v-autocomplete>
  </v-app>
</div>

CSS

body {
  background: #1c2128;
  padding: 20px;
  font-family: 'Roboto', sans-serif;
}

#app {
  background: #1c2128;
}

Vue

new Vue({
  el: "#app",
  
  vuetify: new Vuetify(),
  
  data: {
    descriptionLimit: 60,
    entries: [],
    isLoading: false,
    values: null,
    search: null,
  },
  
  computed: {
  	items () {
      return this.entries.map(entry => {
        const Description = entry.Description.length > this.descriptionLimit
        ? entry.Description.slice(0, this.descriptionLimit) + '...'
        : entry.Description

        return Object.assign({}, entry, { Description })
      })
    }
  },
  
  watch: {
  	search (val) {
    	// Items have already been loaded
      if (this.items.length > 0) return

      // Items have already been requested
      if (this.isLoading) return

      this.isLoading = true

      // Lazily load input items
      fetch('https://api.publicapis.org/entries')
        .then(res => res.json())
        .then(res => {
          this.entries = res.entries
        })
        .catch(err => {
          console.log(err)
        })
        .finally(() => {
          this.isLoading = false
        })
    }
  },
  
  methods: {
  	removeItem (item) {
    	const index = this.values.indexOf(item.API)
      if (index >= 0) this.values.splice(index, 1)
    }
  },
  
  mounted () {
  }
})