JSFiddle - React, Tailwind, and code Playground

by skirtle

HTML

<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
  <no-space-input v-model="text"></no-space-input>
  <p>
    {{ text }}
  </p>
</div>

<p>
  Select text and drag/drop into the input:
</p>
<p>
  abc 123 def
</p>

JavaScript

const NoSpaceInput = {
  template: `
    <input
      ref="input"
      v-model="inputValue"
      @keydown.space.prevent
		>
  `,
  
  props: ['value'],
  
  computed: {
    inputValue: {
      get () {
        return this.value
      },
      set () {
        this.setInputValue(...this.getInputValue().map(this.stripSpaces))
      }
    }
  },
  
  methods: {
    getInputValue() {
      const input = this.$refs.input
      const value = input.value
      const start = input.selectionStart
      const end = input.selectionEnd

      return [
        value.slice(0, start),   // before selection
        value.slice(start, end), // selection
        value.slice(end)         // after selection
      ]
    },
      
    setInputValue(before, selection, after) {
      const input = this.$refs.input
      const start = before.length
      const end = start + selection.length

      const value = input.value = before + selection + after

      input.setSelectionRange(start, end)
      
      this.$emit('input', value)
    },

    stripSpaces(str) {
      return str.replace(/ /g, '')
    }
  }
}

new Vue({
  el: '#app',

  components: {
  	NoSpaceInput
  },

  data () {
    return {
      text: ''
    }
  }
})