概要
Vue.js上で動かせるカレンダーUIライブラリのv-calendarを使って、予めサーバ等から取得した日付ごとのオブジェクトをカレンダー上に突っ込む方法です。
公式ページはこちら
出力結果とソース
先に、出力結果です。
後述する日付ごとのデータを、カレンダー内に表示している内容となります。
続いてこちらのソースです。
※事前に、npm install v-calender
をつかって、v-calendarをインストールしてください。
import Vue from 'vue'
import App from './App.vue'
import VCalendar from 'v-calendar'
Vue.use(VCalendar)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
<template>
<div id="app">
<calendar/>
</div>
</template>
<script>
import calendar from './components/Calendar.vue'
export default {
name: 'app',
components: {
calendar
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
<template>
<div>
<v-calendar
:columns="2"
title-position="center"
>
<template slot='header-title' slot-scope='props'>
{{props.yearLabel}}年{{props.monthLabel}}
</template>
<template slot='day-content' slot-scope='props'>
<div class="cell-header">
{{props.day.day}}
</div>
<div class="cell-content">
<template
v-if="dateList.some(date => date.ymd === dateToYYYYMMDD(props.day.date))">
<div
class="cell-content-line"
v-for="content in getContentFromKey(dateToYYYYMMDD(props.day.date))"
v-bind:key="content">
・{{content}}
</div>
</template>
</div>
</template>
</v-calendar>
</div>
</template>
<script>
export default {
name: 'calendar',
data() {
return {
dateList: [
{ymd: '20190923', contents: ['髪を切る','面談','靴を買う']},
{ymd: '20190914', contents: ['結婚式']},
{ymd: '20190901', contents: ['妹の誕生日']},
{ymd: '20190817', contents: ['海に行く!', '野球の練習']}
]
}
},
computed: {
},
methods: {
dateToYYYYMMDD: function(date) {
let y = date.getFullYear()
let m = ('00' + (date.getMonth()+1)).slice(-2)
let d = ('00' + date.getDate()).slice(-2)
let result = y + '' + m + '' + d
return result
},
getContentFromKey: function(key) {
const target = this.dateList.find((date) => {
return (date.ymd === key)
})
return target.contents
}
}
}
</script>
<style scoped>
.cell-content {
text-align:left;
width: 70px;
height: 50px;
font-size: 50%;
/* border: 1px solid #efefef; */
}
.cell-content-line {
border-bottom: 1px solid #efefef;
}
</style>
かんたんに解説
main.js
については、Vueにv-calendarを読み込ませているだけです。
App.vue
のtemplate内にて、今回カレンダーを作成したCalendar.vueコンポーネントを呼び出しています。
それでは、Calendar.vue
をかんたんに解説します。
先にdataの部分を説明します。
data() {
return {
dateList: [
{ymd: '20190923', contents: ['髪を切る','面談','靴を買う']},
{ymd: '20190914', contents: ['結婚式']},
{ymd: '20190901', contents: ['妹の誕生日']},
{ymd: '20190817', contents: ['海に行く!', '野球の練習']}
]
}
このオブジェクトの配列が、今回表示したいデータとします。
ymdがkeyとなり、同じ日に複数のコンテンツが有る場合を加味しています。
続いて、templateの部分です。
<v-calendar
:columns="2"
title-position="center"
>
v-calenderを呼び出す際に、プロパティを指定しています。
今回は、2列のカレンダーとし、ヘッダを中央に寄せるような設定となっています。
どのようなプロパティが指定できるのかについては、公式に記載されていますので、見てみてください。
<template slot='header-title' slot-scope='props'>
{{props.yearLabel}}年{{props.monthLabel}}
</template>
v-calendarでは、カレンダーの中身を編集する際、パーツに応じたスコープ付きスロットを使用します。
上記のheader-titleというスコープは、カレンダーの年月日ヘッダが記載されている部分となります。
テンプレート内で{{props.yearLabel}}年{{props.monthLabel}}
とすることで、2019年8月といったヘッダの表示に修正しています。(この記載をしないと、デフォルトのヘッダである”2019 08月”といった表示になります。)
<template slot='day-content' slot-scope='props'>
<div class="cell-header">
{{props.day.day}}
</div>
<div class="cell-content">
<template
v-if="dateList.some(date => date.ymd === dateToYYYYMMDD(props.day.date))">
<div
class="cell-content-line"
v-for="content in getContentFromKey(dateToYYYYMMDD(props.day.date))"
v-bind:key="content">
・{{content}}
</div>
</template>
</div>
</template>
今回のキモとなる部分です。
まず、さきほどのheader-titleと同様に、今度はday-contentというスコープのスロットを設定します。day-contentは、カレンダーの日付の部分を表示する箇所となります。
公式を見ていただければわかるように、
props.day
というのはdayオブジェクトであり、更にその中にdayという日付の文字列がはいっています。
そのため、props.day.day
と指定することで、日付を取得しています。
v-if="dateList.some(date => date.ymd === dateToYYYYMMDD(props.day.date))"
の部分で、まずprops.day.dateから取得した日付オブジェクトがdateListに存在するかどうかを見ています。
存在している日付に限り、中の
<div
class="cell-content-line"
v-for="content in getContentFromKey(dateToYYYYMMDD(props.day.date))"
v-bind:key="content">
・{{content}}
</div>
が評価され、contentが描画されるようになっております。
まとめ
v-calendarの設定をつかってカレンダーをカスタマイズしてみましたが、
他にもたくさんのプロパティやイベントが存在するので、ぜひ一度使ってみてください。
今回の記法が冗長である等、改善部分があればぜひご指摘ください。
みていただきありがとうございました。😊