リプレイスなどでやむなく bootstrap-datepicker と Vue.js を連携しなけれならない、という場合の対処方法です。


Laravel での実装を想定しておりますが、ディレクトリ構成などは適宜読み替えれば Laravel 以外でも同様に実装できると思います。

また、Vue.js には 専用の素敵な Datepicker がいくつもありますから、新規開発ではぜひ Vue.js 用のものを使ってくださいね。

Vue.js と jQuery の併用は相性が悪い

Vue.js はリアクティブ系ライブラリと言われます。
仮想のドキュメントツリー (VirtualDOM) を内部で管理し、イベントなどにより VirtualDOM に変更があった場合、DOM 側にそれを反映するという仕組みで動いています。

これに対し、jQuery は DOM を直接操作する、という点が大きく違います。

この2つのライブラリを併用する場合にトラブルになるのは、jQuery 何か DOM 操作を行っても、Vue.js はそれを知りようがない ことに起因します。


具体的に、 bootstrap-datepicker と Vue.js の連携では、次の不具合が発生します。

  • A. Datepicker で日付を入力する
  • B. 他の INPUT タグを操作する
  • C. Aの変更が巻き戻ってしまう

環境について

  • Laravel 5.5
  • Node.js 7.1.x
  • npm 4.5.x
  • Vue.js 2.4.x
  • Bootstrap 3系

Datepicker は次を利用しております。

bootstrap-datepicker
https://github.com/uxsolutions/bootstrap-datepicker

bootstrap-datepicker を日本語化する jQuery プラグインは次を利用しております。

jquery.bootstrap-datetimepicker-ja
https://github.com/cyokodog/jquery.bootstrap-datetimepicker-ja

実装について

ファイル構成

bootstrap-datepicker と、日本語化プラグインを Laravel の public ディレクトリ以下にそのまま設置しました。

public/css/bootstrap-datepicker.min.css
public/js/jquery-3.2.1.min.js
public/js/bootstrap-datepicker.min.js
public/js/bootstrap-datepicker.ja.min.js

読み込み順に影響するため、 webpack.json から jQuery を削除し、public 以下に配置しました。


bootstrap-datepicker は npm からインストールも可能ですが、日本語化プラグインも適用させる場合は複雑になってしまいこの形としました。
はい、私のスキル不足です。

HTML

各種アフィルを次のように読み込みます。

  • HEAD タグ内

    <link href="/css/bootstrap-datepicker.min.css" rel="stylesheet">
    <link href="{{ mix('/css/app.css') }}" rel="stylesheet">
    
  • BODY 閉じタグの手前

    <script src="/js/jquery-3.2.1.min.js"></script>
    <script src="/js/bootstrap-datepicker.min.js"></script>
    <script src="/js/bootstrap-datepicker.ja.min.js"></script>
    <script src="{{ mix('/js/app.js') }}"></script>
    

Vue.jsの実装

Datepicker が 1つ の場合は次のように対応いたします。

template

<template>
  <form class="form-horizontal">
    <div class="form-group">
      <input type="text" class="form-control datepicker"
        v-model="date" />
    </div>
  </form>
</template>

script

<script>
export default {
  mounted() {
    this.setDatePicker()
  },
  data() {
    return {
      date: ""
    }
  },
  methods: {
    setDatePicker() {
      const self = this

      $('.datepicker').datepicker({
        format   : 'yyyy/mm/dd',
        language : 'ja',
        autoclose: true
      })
      $('.datepicker').on('change', (e) => {
        self.date = $(e.target).val()
      })
    }
  }
}
</script>

この処理のポイントは次の部分です。

$('.datepicker').on('change', (e) => {
  self.date = $(e.target).val()
})

jQuery と Vue.js を連携させるにあたって問題になるのが、「jQuery 側の処理を Vue.js が把握していない」ということでしたね。

そのため、「change イベントを拾って Vue.js 側に伝えてあげる」ということをしています。

おまけ:Datepicker が 複数 の場合

前掲のコードでは Datepicker を適用したフォームが複数の場合に対応しておりません。

範囲を表現する daterange の対応ケースを掲載いたします。

template

<template>
  <form class="form-horizontal">
    <div class="form-group">
      <div class="input-group input-daterange" data-provide="datepicker">
        <input type="text" class="form-control datepicker"
          v-model="date_from" data-model-key="date_from" />
        <div class="input-group-addon">to</div>
        <input type="text" class="form-control datepicker"
          v-model="date_to"   data-model-key="date_to" />
      </div>
    </div>
  </form>
</template>

script

<script>
export default {
  mounted() {
    this.setDatePicker()
  },
  data() {
    return {
      date_from : "",
      date_to   : ""
    }
  },
  methods: {
    setDatePicker() {
      const self = this

      $('.datepicker').datepicker({
          format   : 'yyyy/mm/dd',
          language : 'ja',
          autoclose: true
        })
        $('.datepicker').on('change', (e) => {
          const key = $(e.target).attr('data-model-key')
          self[key] = $(e.target).val()
        })
      }
  }
}
</script>

先ほどとの相違点は次です。

  • change イベント発生時に、キー名を動的に取得している
  • html に v-model の対応するキー名を埋め込んだ

要するに、data オブジェクトの何と対応しているかを、HTML で指定してあげる、という処理です。

おわりに

古い実装に縛られず、システムを一新したいとは、プログラマがよく考えることだと思います。

「どうしても Bootstrap の Datepicker にしてください !」という案件が発生した場合に、お役に立てば幸いです。
(検索ワードを見ると、案外ニーズがあるように思います。)

この記事は tomita@atuweb がお届けしました。


初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発

Ethan Brown
出版社:オライリージャパン  発売日:2017-01-20

Amazonで詳細を見る

2017年10月03日:記事の一部を推敲、誤字を修正。