0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue で編集、リバート可能なテキスト

Posted at
  • 普段はテキストだけどダブルクリックするとテキストボックスになるよ
  • Enterかフォーカスアウトで確定されるよ
  • 渡した値はリアクティブに変更されるよ
  • 大丈夫!リバートもできるよ
  • 値が変更された時は一応通知が行くよ
  • 値が空になった時はプレースホルダが表示されるよ
  • リバートボタンとプレースホルダは <tamplate> でカスタマイズできるよ

そのうちnpm化してちゃんとドキュメント書きます

<template>
  <span>
    <!-- bootstrap-vue 使ってたからこれになってるけど普通のinputに差し替えてもいいよ -->
    <b-form-input
      v-if="isEditable"
      ref="content-input"
      :value="value"
      size="sm"
      class="box"
      type="text"
      :style="inputWidth"
      @keypress.enter.native="editableOff"
      @blur="editableOff"
      @input="$emit('input', $event)"
    />
    <span
      v-else
      ref="plain-text"
      class="box"
      @dblclick="editableOn()"
    >
      <span
        v-if="value"
      >
        {{ value }}
      </span>
      <slot
        v-else
        name="placeholder"
      >
        :none:
      </slot>
    </span>
    <span
      v-if="isEdited()"
      @dblclick="revertValue()"
    >
      <slot
        name="revert"
      >
        :rev:
      </slot>
    </span>
  </span>
</template>

<script>
export default {
  props: {
    value: {
      type: String,
      require: true,
      default: ''
    },
    identify: {
      type: Object,
      require: false,
      default: () => {}
    }
  },
  data () {
    return {
      isEditable: false,
      originText: '',
      textWidth: null,
      inputWidth: {
        'min-width': ''
      }
    }
  },
  mounted () {
    this.originText = this.value
  },
  methods: {
    editableOn () {
      this.textWidth = this.$refs['plain-text'].clientWidth
      this.isEditable = true
      this.$nextTick(() => {
        // table の中とかにあると input になった時に縮んじゃう事があるから元のテキストのサイズに合わせるようにしている
        this.inputWidth['min-width'] = (this.textWidth * 1.1) + 'px'
        this.$refs['content-input'].select()
      })
    },
    editableOff () {
      // Enterした時にフォーカスアウトで2回ここに来るからガードつけておく
      if (!this.isEditable) {
        return
      }
      this.isEditable = false
      if (this.isEdited()) {
        this.$emit('editedValue', this.identify, this.value, this.originText)
      }
    },
    isEdited () {
      return this.value !== this.originText
    },
    revertValue () {
      this.$emit('input', this.originText)
      this.$emit('revert')
      this.isEditable = false
    }
  }
}
</script>

<style>
</style>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?