Vue Datalist Component

with vue 2.6

by jorgeluis

HTML

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<link rel="stylesheet" href="https://unpkg.com/buefy/dist/buefy.min.css">
<script src="https://unpkg.com/buefy/dist/buefy.min.js"></script>
<div id="app">
  <tags-datalist :list="scopes" :selected="itemScopes"></tags-datalist>
</div>

<template id="tags-datalist">
  <div>
  
    <div class="tags">
    
      <b-tag 
        v-for="tag in localSelected"
        :key="tag"
        closable
        aria-close-label="Close tag"
        @close="removeItem(tag)">
        {{ tag }}
      </b-tag>
            
    </div>
    
    <div class="field">
      <label v-if="label" class="label">{{ label }}</label>
      <div class="control">
        <input v-model="term" list="item-list" class="input" @change="addItem" 
               name="item-selection" id="item-selection"/>
        <small ref="hint" class="is-size-7 has-text-grey"></small>
        <datalist id="item-list">
          <option v-for="option in localList" v-bind:value="option"  v-bind:label="option"></option>
        </datalist>
      </div>
    </div>

  </div>
</template>

JavaScript

Vue.component('tags-datalist', {
  template: '#tags-datalist',
  name: 'tags-datalist',
  props: {
	  label: null,
  	list: {
    	type: Array,
      default: []
    },
  	selected: {
    	type: Array,
      default: []
    }
  },
  data () {
    return {
    	localList: [],
      localSelected: [],
      term: ''
    }
  },
  created () {
  	this.localList = this.list
  	this.localSelected = this.selected
  },
  methods: {
    addItem: function(e) {
    	this.$refs.hint.innerHTML = ''
      let newItem = e.target.value;

			if (!this.localSelected.includes(newItem)) {
	      this.localSelected.push(newItem)
      } else {
      	this.$refs.hint.innerHTML = 'Already listed'
      }
      this.term = ''
    },
    removeItem: function(item) {
    	this.$refs.hint.innerHTML = ''
			this.localSelected = this.localSelected.filter(i => i !== item)
    }
  }

});


// parent data to use for child props
var vm = new Vue({
  el: '#app',
  data () {
  	return {
      scopes: [
        'one', 'two', 'three'
      ],
      itemScopes: [
        'one', 'three', 'and some other random one from the API?'
      ]
    }
  }
});