LoginSignup
9
5

More than 5 years have passed since last update.

pugで少し複雑なtableを組んでみる

Last updated at Posted at 2019-02-15

ちょうど下表のような感じでrowspanの混じったtableを作る機会があって、いつか使い回すときがくるだろうと思って、Iterationでいい感じにできないか試してみました
表組みサンプル

考え方

ひとまず10行ある中で、小学生に4行(rowspan:4)・中学生に2行(rowspan:2)・一般に4行(rowspan:4)のデータを持つ必要があるので、変数としては以下の様な構成になると思います

variables.pug
-
  const content = [
    {
       category: '小学生',
       data: [
         {
           age: '3年生以下',
           sex: '男女',
           distance: '1km',
           start: '10時00分'
         },
         {
           age: '4年',
           sex: '男女',
           distance: '2km',
           start: '10時15分'
         },
         {
           age: '5年',
           sex: '男女',
           distance: '2km',
           start: '10時30分'
         },
         {
           age: '6年',
           sex: '男女',
           distance: '2km',
           start: '10時45分'
         }
       ]
    },
    {
       category: '中学生',
       data: [
         {
           age: '1〜3年',
           sex: '男子',
           distance: '3km',
           start: '11時15分'
         },
         {
           age: '1〜3年',
           sex: '女子',
           distance: '3km',
           start: '11時00分'
         }
       ]
    },
    {
       category: '一般',
       data: [
         {
           age: '制限なし',
           sex: '女子',
           distance: '3km',
           start: '11時00分'
         },
         {
           age: '29才以下',
           sex: '男子',
           distance: '5km',
           start: '11時30分'
         },
         {
           age: '30才〜49才以下',
           sex: '男子',
           distance: '5km',
           start: '11時30分'
         },
         {
           age: '50才以上',
           sex: '男子',
           distance: '5km',
           start: '11時30分'
         }
       ]
    }
  ]

※ちなみにNOはindex値から取ればいいので省略

とりあえず10行作らないといけないので、Objectをループさせるだけじゃダメ
dataの数だけtrが生成されるようにします

index.pug
tbody
  each val, index in content
    each data, dataIndex in val.data
      tr

現状の出力結果

index.html
<tbody>
  <tr></tr>
  <tr></tr>
  <tr></tr>
  <tr></tr>
  <tr></tr>
  <tr></tr>
  <tr></tr>
  <tr></tr>
  <tr></tr>
  <tr></tr>
</tbody>

理想としては以下の様に1周目だけにNOと部門のtdが生成され、ついでにrowspan属性を付与してほしいわけです

index.html
<tr>
  <td rowspan="4">1</td>
  <td rowspan="4">小学生</td>
  <td>3年生以下</td>
  <td>男女</td>
  <td>1km</td>
  <td>10時00分</td>
</tr>
<tr>
  <td>4年</td>
  <td>男女</td>
  <td>2km</td>
  <td>10時15分</td>
</tr>
<tr>
  <td>5年</td>
  <td>男女</td>
  <td>2km</td>
  <td>10時30分</td>
</tr>
<tr>
  <td>6年</td>
  <td>男女</td>
  <td>2km</td>
  <td>10時45分</td>
</tr>

つまりdataIndexが0のときに、NOと部門のtdを生成する処理をしてあげればよいということになります

index.pug
tbody
  each val, index in content
    each data, dataIndex in val.data
      tr
        // 1周目のときのみNOと部門のtdを生成
        if dataIndex === 0
          // NOの表示
          // rowspanはdataの数を付与
          td(rowspan=val.data.length)
            = index + 1 // indexは0スタートなので+1してあげる

          // 部門の表示
          td(rowspan=val.data.length)
            | #{val.category}

        // あとは毎回の処理
        td= data.age
        td= data.sex
        td= data.distance
        td= data.start

結果

index.html
<tbody>
  <tr>
    <td rowspan="4">1</td>
    <td rowspan="4">小学生</td>
    <td>3年生以下</td>
    <td>男女</td>
    <td>1km</td>
    <td>10時00分</td>
  </tr>
  <tr>
    <td>4年</td>
    <td>男女</td>
    <td>2km</td>
    <td>10時15分</td>
  </tr>
  <tr>
    <td>5年</td>
    <td>男女</td>
    <td>2km</td>
    <td>10時30分</td>
  </tr>
  <tr>
    <td>6年</td>
    <td>男女</td>
    <td>2km</td>
    <td>10時45分</td>
  </tr>
  <tr>
    <td rowspan="2">2</td>
    <td rowspan="2">中学生</td>
    <td>1〜3年</td>
    <td>男子</td>
    <td>3km</td>
    <td>11時15分</td>
  </tr>
  <tr>
    <td>1〜3年</td>
    <td>女子</td>
    <td>3km</td>
    <td>11時00分</td>
  </tr>
  <tr>
    <td rowspan="4">3</td>
    <td rowspan="4">一般</td>
    <td>制限なし</td>
    <td>女子</td>
    <td>3km</td>
    <td>11時00分</td>
  </tr>
  <tr>
    <td>29才以下</td>
    <td>男子</td>
    <td>5km</td>
    <td>11時30分</td>
  </tr>
  <tr>
    <td>30才〜49才以下</td>
    <td>男子</td>
    <td>5km</td>
    <td>11時30分</td>
  </tr>
  <tr>
    <td>50才以上</td>
    <td>男子</td>
    <td>5km</td>
    <td>11時30分</td>
  </tr>
</tbody>

index.pugの中身はすっきりして、あとはvariables.pugを編集するだけで済みますね

これだと最後の11時30分がrowspanされていない?

そんなイレギュラーなものはこんな感じで処理してしまいましょう
上記までの内容が理解できていればなんてことないです

variables.pug
-
  const content = [
    {
      category: '小学生',
      data: [
        {
          age: '3年生以下',
          sex: '男女',
          distance: '1km',
          start: '10時00分'
        },
        {
          age: '4年',
          sex: '男女',
          distance: '2km',
          start: '10時15分'
        },
        {
          age: '5年',
          sex: '男女',
          distance: '2km',
          start: '10時30分'
        },
        {
          age: '6年',
          sex: '男女',
          distance: '2km',
          start: '10時45分'
        }
      ]
    },
    {
      category: '中学生',
      data: [
        {
          age: '1〜3年',
          sex: '男子',
          distance: '3km',
          start: '11時15分'
        },
        {
          age: '1〜3年',
          sex: '女子',
          distance: '3km',
          start: '11時10分'
        }
      ]
    },
    {
      category: '一般',
      data: [
        {
          age: '制限なし',
          sex: '女子',
          distance: '3km',
          start: '11時00分'
        },
        {
          age: '29才以下',
          sex: '男子',
          distance: '5km',
          start: '11時30分',
          colspan: 3
        },
        {
          age: '30才〜49才以下',
          sex: '男子',
          distance: '5km',
        },
        {
          age: '50才以上',
          sex: '男子',
          distance: '5km',
        }
      ]
    }
  ]
index.pug
tbody
  each val, index in content
    each data, dataIndex in val.data
      tr
        if dataIndex === 0
          td(rowspan=val.data.length)
            = index
          td(rowspan=val.data.length)
            | #{val.category}
        td= data.age
        td= data.sex
        td= data.distance
        if data.start
          td(rowspan=data.colspan)= data.start
index.html
<tbody>
  <tr>
    <td rowspan="4">0
    </td>
    <td rowspan="4">小学生</td>
    <td>3年生以下</td>
    <td>男女</td>
    <td>1km</td>
    <td>10時00分</td>
  </tr>
  <tr>
    <td>4年</td>
    <td>男女</td>
    <td>2km</td>
    <td>10時15分</td>
  </tr>
  <tr>
    <td>5年</td>
    <td>男女</td>
    <td>2km</td>
    <td>10時30分</td>
  </tr>
  <tr>
    <td>6年</td>
    <td>男女</td>
    <td>2km</td>
    <td>10時45分</td>
  </tr>
  <tr>
    <td rowspan="2">1
    </td>
    <td rowspan="2">中学生</td>
    <td>1〜3年</td>
    <td>男子</td>
    <td>3km</td>
    <td>11時15分</td>
  </tr>
  <tr>
    <td>1〜3年</td>
    <td>女子</td>
    <td>3km</td>
    <td>11時10分</td>
  </tr>
  <tr>
    <td rowspan="4">2
    </td>
    <td rowspan="4">一般</td>
    <td>制限なし</td>
    <td>女子</td>
    <td>3km</td>
    <td>11時00分</td>
  </tr>
  <tr>
    <td>29才以下</td>
    <td>男子</td>
    <td>5km</td>
    <td rowspan="3">11時30分</td>
  </tr>
  <tr>
    <td>30才〜49才以下</td>
    <td>男子</td>
    <td>5km</td>
  </tr>
  <tr>
    <td>50才以上</td>
    <td>男子</td>
    <td>5km</td>
  </tr>
</tbody>
9
5
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
9
5