ちょうど下表のような感じで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>