LoginSignup
11
12

More than 5 years have passed since last update.

Vue.jsで可変長なテキストフィールドを作る

Last updated at Posted at 2017-12-16

この記事はVue.js #1 Advent Calendar 2017の16日目の記事です。

もともとは「Vuetifyを使って爆速でマテリアルデザインのコンポーネントをつくる」という記事をあげる予定でしたが、間に合わなかったので過去に社内Qiitaに載せたものを紹介します。(Vuetifyに関する記事はいずれ書きます)

はじめに

基本的にHTMLのテキストフィールドは固定長で作られますが、
現在取り組んでいるプロジェクトで可変長のテキストフィールドが必要になり、探してみても意外となかったのでつくってみました。

設計方針

設計というほど大げさなものではないですが、基本的なアイディアはこんな感じ。

  • visibility: hiddenにしたspanを用意
  • 可変のテキストフィールドと同じスタイルを適用
  • テキストフィールドの文字をspanのテキストと同期させて長さを得る
  • 長さをテキストフィールドに反映

はじめは入力されているテキストの文字数をカウントして長さを変えようかと思いましたが、
全角半角がまざると面倒なので却下しました。

実装

Vue.jsを使った実装の上でのポイントはこんな感じ。

  • v-modelを使ってもinput文字のバインドはできるが、全角入力中の文字がとれないので@inputを使って入力イベントをフックする
  • spanposition: absolute (or fixed)にしないとclientWidth0になる
  • spanwhite-space: nowrapをつけないとspanが改行してしまい、正常な幅がとれない
  • vm.$nextTickを使わないとdomの更新前に幅の計算が走ってしまう
  • 入力しやすいように少し幅を大きく取る(今回は+10px)

コード

pugsassを使っています。

template(pug)
#flexible-input
  input(
    type="text"
    v-bind:value="text"
    v-bind:style="style"
    @input="input"
  )
  span(ref="hidden") {{text}}
script(js)
new Vue({
  el: '#flexible-input',
  data() {
    return {
      text: "初期値",
      style: "",
    }
  },
  mounted() {
    this.updateStyle() 
  },
  methods: {
    updateStyle() {
      this.style = `width: ${this.$refs.hidden.clientWidth + 10}px;`
    },
    input(e) {
      this.text = e.target.value
      this.$nextTick(() => this.updateStyle())
    }
  }
})
style(sass)
input
  border: 1px solid lightgrey
  min-width: 100px

span
  visibility: hidden
  position: fixed
  white-space: nowrap

デモ

GIF

テキストの変化が分かるようにspanを表示させています。

9bb3af12-fafc-6de6-71b3-6c85cbfbcca5.gif

Codepen

See the Pen Flexible Input by totto357 (@totto357) on CodePen.

まとめ

今回はVue.jsで可変長のテキストフィールドを作成しました。
必要な機能を追加してこのコンポーネントをnpmパッケージとして公開できるようにしたいですね。

17日目は @SatohJohn さんのVue-Routerのナビゲーションガードを使ってみるです!

11
12
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
11
12