Skip to content

Instantly share code, notes, and snippets.

@andreapavoni
Last active November 17, 2017 14:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andreapavoni/ae2fe61ef946606017c72c0ad420a575 to your computer and use it in GitHub Desktop.
Save andreapavoni/ae2fe61ef946606017c72c0ad420a575 to your computer and use it in GitHub Desktop.
<tags-input>
<%= hidden_input form, :tags, value: [] , class: "input" %>
</tags-input>
<template>
<div @click="focusNewTag()" class="vue-input-tag-wrapper">
<span v-for="(tag, index) in tags" class="input-tag">
<span>{{ tag }}</span>
<a @click.prevent.stop="remove(index)" class="remove"></a>
</span>
<input type="text" v-model="newTag" v-on:keydown.delete.stop="removeLastTag()" v-on:keydown.enter.prevent.stop="addNew(newTag)" v-on:keydown.188.prevent.stop="addNew(newTag)" class="new-tag"/>
<slot></slot>
</div>
</template>
<script>
import Vue from 'vue'
const validRegexp = /^(\w|\s|\d)+$/
export default Vue.component('input-tags', {
data() {
return {
newTag: '',
tags: []
}
},
methods: {
focusNewTag() { this.$el.querySelector('.new-tag').focus(); },
addNew(tag) {
tag = tag.trim()
if (tag && !this.tags.includes(tag) && validRegexp.test(tag)) {
this.tags.push(tag)
}
this.newTag = ''
},
remove(index) { this.tags.splice(index, 1) },
removeLastTag() {
if (!this.newTag) { this.tags.pop() }
}
},
mounted() {
this.tags = this.$slots.default[0].elm.value.split(",").filter((tag) => {
return tag.length !== 0
})
},
watch: {
tags() { this.$slots.default[0].elm.value = this.tags }
},
})
</script>
<style>
.vue-input-tag-wrapper {
background-color: #fff;
border: 1px solid #ccc;
overflow: hidden;
padding-left: 4px;
padding-top: 4px;
cursor: text;
text-align: left;
-webkit-appearance: textfield;
}
.vue-input-tag-wrapper .input-tag {
background-color: #cde69c;
border-radius: 2px;
border: 1px solid #a5d24a;
color: #638421;
display: inline-block;
font-size: 13px;
font-weight: 400;
margin-bottom: 4px;
margin-right: 4px;
padding: 3px;
}
.vue-input-tag-wrapper .input-tag .remove {
cursor: pointer;
font-weight: bold;
color: #638421;
}
.vue-input-tag-wrapper .input-tag .remove:hover {
text-decoration: none;
}
.vue-input-tag-wrapper .input-tag .remove::before {
content: "\00d7";
}
.vue-input-tag-wrapper .new-tag {
background: transparent;
border: 0;
color: #777;
font-size: 13px;
font-weight: 400;
margin-bottom: 6px;
margin-top: 1px;
outline: none;
padding: 4px;
padding-left: 0;
width: 80px;
}
.vue-input-tag-wrapper.read-only {
cursor: default;
}
</style>
import Vue from 'vue'
import TagsInput from './vue/tags-input'
export default function() {
if (document.querySelector('tags-input')) {
return new Vue({
el: 'tags-input',
components: { TagsInput }
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment