
九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、前回はVue + DataTableにチェックボックスで複数削除の機能をつけるというVue
とjQuery
を連携させる方法をご紹介しました。
Vue
は、JavaScript
の開発をより効率的にしてくれますが、特定の機能だけを考えるとまだまだjQuery
の機能を使うほうが高速に実装することができたりします。
そのため、jQuery
をベースにしているBootstrap
を使った場合でも同じで、例えば以下のようなモーダルはそんな便利機能のうちのひとつです。
そして、個人的ですが地味に便利だと思うBootstrap
の機能があります。
それは、
ツールチップ(マウスを合わせるとテキストをポップアップしてくれる機能)
です。
これのことですね ↓↓↓
なぜかというと、全ての項目に説明文をつけてしまうとページ内容がごちゃごちゃしてしまうので、例えば「?」マークのアイコンにツールチップをつけて「ここの意味はこうですよ」と教えてあげるとユーザビリティ的にもグッドだからです。
ただ、Vue
+ Bootstrap
を使っている場合にうまく動かない例が出てくることがあるので、その対処法をこの記事でシェアしておきたいと思います。
ぜひ皆さんのお役に立てると嬉しいです
開発環境: Vue 2.6
目次 [非表示]
上手く動く例
まずはVue
とツールチップを使った上手く動く例を紹介します。
ただし、この書き方はVue
としての動きがほぼないので、ウェブ開発としては使えませんが、順を追って見ていきたいのであえて載せておきます。
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<div id="app">
<div class="p-2" v-for="color in colors">
<button
type="button"
class="btn btn-dark"
data-toggle="tooltip"
:title="color +'のツールチップ'">{{ color }}</button>
</div>
<hr>
<a class="m-2" href="#" @click.prevent="changeColors">色を変更</a>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
<script>
new Vue({
el: '#app',
data: {
colors: ['赤', '青', '黄色', '白', '黒']
},
mounted() {
$('[data-toggle="tooltip"]').tooltip();
}
});
</script>
</body>
</html>
内容としてはとてもシンプルで、Vue
にcolors
という色の名前が入った変数を用意し、HTML側でv-for
を使ってループさせます。
そして、そのループで作成したボタンにBootstrap
のtooltip()
を実行してツールチップを起動させるようにしています。
これを実行した結果はこうなります。
上手く動いていますね。
さっきのコードを拡張させる(動かない例)
では続いて、さっきのコードをより動的に動くものに変更したくなったとします。
例えば、色のデータをAjax
で取得する場合やパラメータによって色データを切り替えたい場合ですね。
では、そんな場合のコードです。
// 【注意】この例は上手くいません
new Vue({
el: '#app',
data: {
colors: [] // 初期値は色データなし
},
mounted() {
// ここで色データをセットする
this.colors = ['赤', '青', '黄色', '白', '黒'];
// ツールチップ
$('[data-toggle="tooltip"]').tooltip();
}
});
一見するとこのコードを見ると上手くツールチップが起動しそうにみえます。なぜなら、colors
をセットしてからtooltip()
を実行しているからです。
しかし、実際にはツールチップは起動できません。
これはなぜか???
それは、この場合だと tooltip() が呼ばれた時にターゲットになる <button>ボタン</button> はまだ存在してないからです。
最初の上手く行ったバージョンの例を思い出してみてください。あのときは初期値としてdata
にcolors
という色データが入っていました。
そして、Vue
のmounted()
はページの準備が完了した時、つまりボタンも含めたHTMLが用意されてから呼ばれるメソッドなので、すでにツールチップを表示するボタンも存在していたことになります。
しかし、拡張版の場合は色データを変更しただけでHTMLデータはまだ変更されていないということになります。
では、どう対応すればいいのか??
そこで登場するのがVue
が用意してくれているnextTick()
というメソッドです。
nextTick() は、HTMLが作成された後に実行されるメソッドで、一種のコールバック関数になります。
では、実際にコードを見てみましょう。
new Vue({
el: '#app',
data: {
colors: []
},
mounted() {
this.colors = ['赤', '青', '黄色', '白', '黒'];
Vue.nextTick(() => {
// ここはHTMLの作成後に実行される
$('[data-toggle="tooltip"]').tooltip();
});
}
});
内容としては、先ほどのコードにnextTick()
を追加しただけですが、実行するとこのコードはうまく動くようになります。
データの中身がよく変更になる場合は??
先ほどの例では、色データはmounted()
の中で1回だけ変更されるようになっていました。
ただ、開発内容によってはv-for
で表示するデータが頻繁に変更になる場合も多いと思います。そんな場合はどうすればいいのでしょうか。
その答えは、watch
です。
watch
はある特定のデータが変更になったら必ず呼ばれるメソッドを作ることができるので、以下のようにすることでcolors
の中身が変更になるごとにtooltip()
を実行することができるようになります。
※ ちなみに色データを手動で変更できるようにchangeColors()
というメソッドもつけています。
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<div id="app">
<div class="p-2" v-for="color in colors">
<button
type="button"
class="btn btn-dark"
data-toggle="tooltip"
:title="color +'のツールチップ'">{{ color }}</button>
</div>
<hr>
<a class="m-2" href="#" @click.prevent="changeColors">色を変更</a>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
<script>
new Vue({
el: '#app',
data: {
colors: []
},
methods: {
changeColors() {
this.colors = ['金', '銀', '銅'];
}
},
watch: {
colors() {
Vue.nextTick(() => {
$('[data-toggle="tooltip"]').tooltip();
})
}
},
mounted() {
this.colors = ['赤', '青', '黄色', '白', '黒'];
}
});
</script>
</body>
</html>
でも、これだと色を変更しても前のデータでポップアップされてしまう・・・
watch
を使うと色データが変わってもツールチップは起動するようになりますが、実はこのままでは1つ問題があります。
もし動的にツールチップの内容を変更するような(今回のような)場合だと、前のツールチップの内容が残ってしまうのです。
こんなカンジです
↓↓↓
「金」に変更になった後も最初の「赤のツールチップ」と表示されていますね。
これは、tooltip()
はその内容をdata-original-title
というプロパティに格納するのですが、data-*
はキャッシュされる仕様になっているためで、これに対応するには直接このプロパティを変更する必要があります。
<button
type="button"
class="btn btn-dark"
data-toggle="tooltip"
:data-original-title="color +'のツールチップ'">{{ color }}</button>
これですべてOKです。
お疲れ様でした
テストしてみる
全ての変更を実施したコードを実行してみましょう。
はい!上手く動きました。
今回のソースコード
ちなみに今回作成した最終コードは以下のとおりです。
ご自身の開発で自由に応用して使ってください。
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<div id="app">
<h3 class="p-2">Vue + Bootstrapでツールチップを実装</h3>
<div class="p-2" v-for="color in colors">
<button
type="button"
class="btn btn-dark"
data-toggle="tooltip"
:data-original-title="color +'のツールチップ'">{{ color }}</button>
</div>
<hr>
<a class="m-2" href="#" @click.prevent="changeColors">色を変更</a>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
<script>
new Vue({
el: '#app',
data: {
colors: []
},
methods: {
changeColors() {
this.colors = ['金', '銀', '銅'];
}
},
watch: {
colors() {
Vue.nextTick(() => {
$('[data-toggle="tooltip"]').tooltip({
title() {
return $(this).attr('title');
}
});
})
}
},
mounted() {
this.colors = ['赤', '青', '黄色', '白', '黒'];
}
});
</script>
</body>
</html>
ちなみに
通常のBootstrap
を使っているとコンソールに以下のようなエラーが表示されることがあります。
TypeError: Bootstrap's tooltips require Popper.js
これは、「Bootstrap
でツールチップを使うにはPopper.js
が必要です」という意味になります。
そのため、今回のようにCDN
を使ってBootstrap
を読み込むためには以下のようにBundle
バージョンを読み込むといいでしょう。
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
もしくは、Popper.js
を追加で読み込んでください。
おわりに
ということで、今回はVue
+ Bootstrap
でツールチップが動かない場合の対処法をお届けしました。
今回のツールチップに限らずですが、Vue
+jQuery
を使っていて「あれ、上手くいかないぞ」ということがあればnextTick
を使うことを試してみるといいと思います。
また、今回とは関係ない話ですがBootstrap 4
にはp-*
(*は数字)と書くだけでパディングを設定できるんですね。m-*
はマージンです。
もう一つの人気CSSフレームワークのtailwind CSS
には同様のものがあるので、「これBootstrap
にもあったらな〜」なんて思ってたら普通にありました(なんだったら
Bootstrap
が本家だったりするのかな???)
ということで、また1つ賢くなれたVue
記事でした。
ぜひ皆さんもVue
でツールチップを試してみてくださいね。
ではでは〜!