2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【React】動的テーブル セル結合

Last updated at Posted at 2021-05-24

動的テーブルでセル結合をする

目指すかたち
civilization VI wiki
civ6table.JPG

テーブルの特徴
・一つのセルに要素が2つ以上あったりなかったりする
・同要素でもまとまってないセルが存在する(コスト)

想定する動き
・DBからテーブルデータ引っ張ってきて(fetch)ならべる

問題
・DBから引っ張ってきて普通に並べると一列ずつになっちゃう

const items = [
  {A: "A1", B: "B1" , C: "C1"},
  {A: "A1", B: "B2" , C: "C1"},
  {A: "A1", B: "B2" , C: "C2"},
  {A: "A2", B: "B1" , C: "C1"},
  {A: "A2", B: "B1" , C: "C2"},
];

const ItemsTableOld = () => {
  return(
    <table border="1">
      {items.map((item) => {
        return(
          <tr>
            <td >{item.A}</td>
            <td >{item.B}</td>
            <td >{item.C}</td>
          </tr>
        )
      })}
    </table>
  )
}

結果
tebleold.JPG

同一の要素は一つにまとめたい。
rowspanを設定してセルを結合するのだが、広げた分よけいに描画しないようにする。
DBにrowspanの値と描画するかどうかのbooleanを入れておくしかない?

const items = [
  {A: "A1",drawA:true , rowA:3 , B: "B1" ,drawB:true  ,rowB:1, C: "C1",drawC:true ,rowC:2},
  {A: "A1",drawA:false, rowA:0 , B: "B2" ,drawB:true  ,rowB:2, C: "C1",drawC:false,rowC:0},
  {A: "A1",drawA:false, rowA:0 , B: "B2" ,drawB:false ,rowB:0, C: "C2",drawC:true ,rowC:1},
  {A: "A2",drawA:true , rowA:2 , B: "B1" ,drawB:true  ,rowB:2, C: "C1",drawC:true ,rowC:1},
  {A: "A2",drawA:false , rowA:0 , B: "B1" ,drawB:false ,rowB:0, C: "C2",drawC:true ,rowC:1},
];

const ItemsTable = () => {
  return (
    <table border="1">
      {items.map((item) => {
        return(
          <tr>
            {item.drawA && <td rowSpan={item.rowA}>{item.A}</td>}
            {item.drawB && <td rowSpan={item.rowB}>{item.B}</td>}
            {item.drawC && <td rowSpan={item.rowC}>{item.C}</td>}
          </tr>
        )
      })}
    </table>
  )
}

結果
tablenew.JPG

一応動的にテーブルを描画しつつセル結合もできている。
問題点
・テーブルがきたない
・rowspanを定義するrowA,rowB,rowCは省略できないか
・オブジェクトからあらかじめ同一の要素を抜き出してその数を数えて、それをrowspanとできないか
⇒隣り合ってないけど同一の要素を抽出してrowspanがおかしくなるので難しい
・描画するかどうかを定義するboolean drawA,drawB,drawCはロジックで外に出せないか
⇒出せました
・同一要素一つ目だけdraw:trueとして、それ以外をdraw:falseとするにはどうしたらよいか
⇒テーブルに持たせればおk
・同一要素でもまとめたくない要素の存在
⇒やはりテーブルにrowspanを持たせて任意で変えられるようにするのが良さそう

改善1:booleanは消せる

const items = [
  {A: "A1", rowA:3 , B: "B1" ,rowB:1, C: "C1",rowC:2},
  {A: "A1", rowA:0 , B: "B2" ,rowB:2, C: "C1",rowC:0},
  {A: "A1", rowA:0 , B: "B2" ,rowB:0, C: "C2",rowC:1},
  {A: "A2", rowA:2 , B: "B1" ,rowB:2, C: "C1",rowC:1},
  {A: "A2", rowA:0 , B: "B1" ,rowB:0, C: "C2",rowC:1},
];

const ItemsTable = () => {
  return (
    <table border="1">
      {items.map((item) => {
        return(
          <tr>
            {item.rowA > 0 && <td rowSpan={item.rowA}>{item.A}</td>}
            {item.rowB > 0 && <td rowSpan={item.rowB}>{item.B}</td>}
            {item.rowC > 0 && <td rowSpan={item.rowC}>{item.C}</td>}
          </tr>
        )
      })}
    </table>
  )
}

データベースから取ってくるのも目標なので、こんなん用意しました。

Web キャプチャ_29-5-2021_235517_127.0.0.1.jpeg

このレコードをreactでフェッチして同じように並べてみます。

import React,{useState, useEffect} from 'react';
import axios from 'axios';

const FetchedTable = () => {
  const[alphas, setAlphas] = useState([])
  useEffect(() => {
    axios.get('http://127.0.0.1:8000/api/v1/alphabet')
    .then(res => setAlphas(res.data));
  },[]);

  return(
    <table border="1">
      {alphas.map(alpha => {
        return(
          <tr>
            {alpha.rowspanA > 0 && <td rowSpan={alpha.rowspanA}>{alpha.characterA}</td>}
            {alpha.rowspanB > 0 && <td rowSpan={alpha.rowspanB}>{alpha.characterB}</td>}
            {alpha.rowspanC > 0 && <td rowSpan={alpha.rowspanC}>{alpha.characterC}</td>}
          </tr>
        )
      })}
  </table>
  )
}

/*index = 0の場合描画する*/
/*前回ループと値が違う array[index - 1].X !== item.X 場合描画する*/

const DinamicTable = () => {
  return(
    <>
      <p>fetched table</p>
      <FetchedTable/>
    </>

  )
}

export default DinamicTable;

結果
image.png

とりあえず一つ目標達成。

アイデア
①バックエンドの方でカンマ区切りの文字列を登録
②フロント側でsplitする
これならrowspanを使わなくて済む

2
3
2

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
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?