vue.jsでタグのAutocompleteを実装 - inokawablog

vue.jsでタグのAutocompleteを実装

Laravelとvuetifyでアプリを作成していたのですが、Vuetifyに欲しいタグの機能がなかったので他で代用

 

Vue Tags Inputを使う。わかりやすくてシンプルで綺麗。これで十分。

 

インストール

npm install @johmun/vue-tags-input

 

使い方

<template>
  <div>
    <vue-tags-input
      v-model="tag"
      :tags="tags"
      @tags-changed="newTags => tags = newTags"
    />
  </div>
</template>

<script>
import VueTagsInput from '@johmun/vue-tags-input';

export default {
  components: {
    VueTagsInput,
  },
  data() {
    return {
      tag: '',
      tags: [],
    };
  },
};
</script>

 

一番シンプルな使い方

tagは入力中のテキスト

tagsはすでに入力されたもの

@tags-changedは

newTagsはtags + tagした配列。つまり入力した後の配列

次にautocomplete

 

autocomplete

ついでにバリデーションも追加

<template>
  <div>
    <vue-tags-input
      v-model="tag"
      :tags="tags"
      :autocomplete-items="filteredItems"
      :validation="validation"
      @tags-changed="newTags => tags = newTags"
      @before-adding-tag="checkTag"
    />
  </div>
</template>

<script>
import VueTagsInput from '@johmun/vue-tags-input';

export default {
  components: {
    VueTagsInput,
  },
  data() {
    return {
      tag: '',
      tags: [],
      validation: [{
        classes: 'max-length',
        rule: tag => tag.text.length > 20,
      }],
      autocompleteItems: [{
        text: 'Spain',
      }, {
        text: 'France',
      }, {
        text: 'USA',
      }, {
        text: 'Germany',
      }, {
        text: 'China',
      }],
    };
  },
  methods:{
      checkTag(obj) {
         if (obj.tag.text.length > 20) console.log('タグは20文字まで')
         else obj.addTag();
      },
  },
  computed: {
    filteredItems() {
      return this.autocompleteItems.filter(i => {
        return i.text.toLowerCase().indexOf(this.tag.toLowerCase()) !== -1;
      });
    },
  },
};
</script>

 

autocompleteitemsはkeyがtextでないと機能しない

ここでのdataのvalidationは表示されているタグが赤く表示される。@before-adding-tagは@tags-changedの前に発火する。実際のvalidationは@before-adding-tagのcheckTagで行なっている。

 

まとめ

よく使う機能だと思うので、Vue.js用のUIコンポーネントフレームワークでこれ標準実装してくれればいいと思う。