ブログ

読んで思い出す。忘れるために書く

既存のデータを <table/> にプロットする

teratail.com

目的・ゴール

質問を見ててテーブル要素にデータを一覧として表示させてみたくなった

結果

f:id:innocent-zero:20180416212527p:plain

暫定的にこうなった

表示させるのに都合のいいデータを用意したので、値はほぼ可変

<table/> に表示させたい場合、サーバ側で、フロント側が表示しやすいようにデータの整形を頑張る必要があるのかもわからない

サーバとの連携については考えることができてない

機能は:

  • 教科をクリックすると背景色が変わる
  • 時間割の表示時間が現在時刻を過ぎているとクリック不能になる

というのを書いた

登場するコンポーネント

  • TimeTable.vue: <table/> を利用してデータの整形と表示をする
  • ToggleLabel.vue: クリックすることで背景色を変える、チェックボックス付きのラベル

コンポーネントの内容

TimeTable.vue:

<template>
  <div>
    <table>
      <tr>
        <td></td>
        <td v-for="date in timeTable.days">{{ date }}</td>
      </tr>
      <tr v-for="data in timeTable.reservationData" :key="data.time">
        <td :class="expired(data.endTime)">{{ data.startTime }} ~ {{ data.endTime }}</td>
        <td v-for="v in data.value" :key="v">
          <toggle-label :id="v + data.startTime" :expired="isExpired(data.endTime)">
            {{ v }}
          </toggle-label>
        </td>
      </tr>
    </table>
  </div>
</template>

<script>
import TableData from '@/components/TableData'
import ToggleLabel from '@/components/ToggleLabel'
let moment = require('moment')

export default {
  name: 'TimeTable',
  data () {
    return {
      timeTable: {
        days: ['10/01', '10/02', '10/03', '10/04', '10/05', '10/06', '10/07'],
        reservationData: [
          {
            'startTime': '09:00',
            'endTime': '10:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          },
          {
            'startTime': '10:00',
            'endTime': '11:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          },
          {
            'startTime': '11:00',
            'endTime': '12:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          },
          {
            'startTime': '12:00',
            'endTime': '13:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          },
          {
            'startTime': '13:00',
            'endTime': '14:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          },
          {
            'startTime': '14:00',
            'endTime': '15:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          },
          {
            'startTime': '15:00',
            'endTime': '16:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          },
          {
            'startTime': '16:00',
            'endTime': '17:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          },
          {
            'startTime': '17:00',
            'endTime': '18:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          },
          {
            'startTime': '18:00',
            'endTime': '19:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          },
          {
            'startTime': '19:00',
            'endTime': '20:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          },
          {
            'startTime': '20:00',
            'endTime': '21:00',
            'value': ['国語', '算数', '理科', '社会', '体育', '生活', '音楽']
          }
        ]
      }
    }
  },
  methods: {
    expired: function (v) {
      let timeFormat = 'HH::mm'
      // Not well tested but it may be worked.
      // let currentTime = moment(new Date(), timeFormat)

      // Fixed value for debug
      let currentTime = moment('12:00', timeFormat)

      let targetTime = moment(v, timeFormat)

      return (
        targetTime.isBefore(currentTime) ? 'expired' : 'available'
      )
    },
    isExpired: function (v) {
      let format = 'HH::mm'
      // let currentTime = moment(new Date(), format)
      let currentTime = moment('12:00', format)
      let targetTime = moment(v, format)
      return targetTime.isBefore(currentTime)
    }
  },
  components: {
    'table-data': TableData,
    'toggle-label': ToggleLabel
  }
}
</script>

<style scoped>
table {
  border: 2px solid #AAAAAA;
}
.expired {
  background: #A9A9A9;
  pointer-events: none;
}
</style>

ToggleLabel.vue:

<template>
  <div>
    <input :id ="id" type="checkbox" :value="value">
    <label :for="id" :class="isExpired">
      <slot></slot>
    </label>
  </div>
</template>

<script>

export default {
  name: 'ToogleLabel',
  data () {
    return {}
  },
  props: {
    'id': {
      'type': String,
      'default': ''
    },
    'expired': {
      'type': Boolean,
      'default': false
    },
    'value': {
      'type': String,
      'defualt': ''
    }
  },
  computed: {
    isExpired: function () {
      return this.expired ? 'expired' : 'available'
    }
  }
}
</script>

<style scoped>
label {
  display: inline-block;
  padding: 3px 0px 3px 0px;
  width: 106%;
}
label.expired {
  background: #A9A9A9;
  pointer-events: none;
}
input {
  display: none;
}
:checked + label {
  background: #CEFECE;
}
</style>