0
0

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.

【Vue】テーブル操作エキスパートへの道。ボタンクリック列でを削除する方法

Posted at

ボタンクリックで表から列を削除する方法について。

これまで、

v-forを使ったテーブルの作成
表で複数選択を可能にする方法
ボタンクリックで行を追加する方法
ボタンクリックで列を追加する方法
ボタンクリックで列を追加する方法

について確認したので、次のステップとして列を削除する方法を確認する。

##実装イメージ

image.png

↓ 選択中のセルを削除する

image.png

##考え方

  1. 現在選択中のセルの有無を判断
  2. 現在選択中のセルの列番号を取得する
  3. 表から選択中のセル以外を残す
  4. 選択を解除

##実装

    removeColumn(){
      //選択中のセルがある場合のみ処理を実行
      if(this.currentCells.length != 0){

        //削除したいセル番号を抽出(重複削除)
        const cellIndicesToRemove = new Set(
          this.currentCells.map(cell => cell.xxxcellIndex )
        )

        //削除したい列を除外
        this.rows.map((row)=> 
          row.table_cells = (row.table_cells.filter((x, cellIndex)=>
            !cellIndicesToRemove.has(cellIndex)
          ))
        )

        //選択中のセルを解除
        this.currentCells = []
      }
    }

####1. 現在選択中のセルの有無を判断
if(this.currentCells.length != 0)

現在選択中のセルの行列番号を格納する配列の要素の長さで判断する。


####2. 現在選択中のセルの列番号を取得する
const cellIndicesToRemove = new Set(
          this.currentCells.map(cell => cell.xxxcellIndex )
        )

mapメソッドを使って、現在選択中の列番号を抽出する。
重複削除するため、Setオブジェクトに変換する。


####3.表から選択中のセル以外を残す
        //削除したい列を除外
        this.rows.map((row)=> 
          row.table_cells = (row.table_cells.filter((x, cellIndex)=>
            !cellIndicesToRemove.has(cellIndex)
          ))
        )

filterとSetオブジェクトのhasメソッドを使って、現在選択中以外のセル番号のみを残す。

mapメソッドで行要素を一つづつ抜き出す。
filterメソッドで各行の列要素を一つづつ抜き出し、!とhasメソッドで番号が一致したセルを除外していく。

filterは非破壊のため、不要なセルを排除した行を元の行に代入する。


####4. 選択を解除
      this.currentCells = []

現在選択中のセルを空にする。


##フルコード
<template>
  <div>
    <p>〜TmpRemoveColumn.vue〜</p>
    <p>currentCells : {{currentCells}}</p>
    

    <p>
      <button
        @click="removeColumn"
      >列を削除
      </button>
    </p>

    <table>
      <template v-for="(tr, rowIndex) in rows">
        <tr :key="rowIndex">
          <template v-for="(cell, cellIndex) in tr.table_cells">
            <th :key="cellIndex" 
                v-if="cell.cell_type == 'TH'"
                :class="{'is-active': isActive(rowIndex, cellIndex)}"
                @click="clickCell($event)">
              ( {{rowIndex}} , {{cellIndex}} )
            </th>
          
            <td :key="cellIndex" 
                v-else-if="cell.cell_type == 'TD'"
                :class="{'is-active': isActive(rowIndex, cellIndex)}"
                @click="clickCell($event)">
              ( {{rowIndex}} , {{cellIndex}} )
            </td>
          </template>
        </tr>
      </template>
    </table>

  </div>
</template>

<script>
export default {
  data(){
    return{
      currentCells:[],
      rows: [
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
                {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
      ]
    }
  },
  methods:{
    //isActiveの判定
    //currentCellsの中にあればtrueにする
    //指定した行列番号の要素がある=数値が-1以外ならtrueにする。
    isActive(rowIndex, cellIndex){
      return this.currentCells.findIndex((elem) =>
        elem.xxxrowIndex == rowIndex && elem.xxxcellIndex == cellIndex
        ) > -1
    },

    clickCell(event){
      //クリックされたセルの情報
      const cell = event.target
      const tr = event.target.parentNode

      //クリックされたセルが既に選択されている場合は、配列から削除する
      if(this.isActive(tr.rowIndex, cell.cellIndex)){
        
        //選択中の配列の何番目の要素かを求める
        const rmIndex = this.currentCells.findIndex((elem)=>
          elem.xxxrowIndex == tr.rowIndex && elem.xxxcellIndex == cell.cellIndex 
        )

        //選択した要素を選択中の配列から削除する
        this.currentCells = [
          ...this.currentCells.slice(0, rmIndex),
          ...this.currentCells.slice(rmIndex + 1)
        ]

      } else{
        this.currentCells = [
          ...this.currentCells,
          {
            xxxrowIndex: tr.rowIndex,
            xxxcellIndex: cell.cellIndex
          }
        ]
      }
    },
    removeColumn(){
      //選択中のセルがある場合のみ処理を実行
      if(this.currentCells.length != 0){

        //削除したいセル番号を抽出(重複削除)
        const cellIndicesToRemove = new Set(
          this.currentCells.map(cell => cell.xxxcellIndex )
        )

        //削除したい列を除外
        this.rows.map((row)=> 
          row.table_cells = (row.table_cells.filter((x, cellIndex)=>
            !cellIndicesToRemove.has(cellIndex)
          ))
        )

        //選択中のセルを解除
        this.currentCells = []
      }
    }
  }
}
</script>

<style lang="scss" scoped>
table{
  width: 80%;

  th,td{
    border: thin solid rgba(0, 0, 0, 0.12);
    text-align: center;
    color: gray;
  }
  th{
    background: #ccc;
  }
  th, td{
    //選択状態
    &.is-active{
      border: 1px double #0098f7;
    }
  }
}
button{ 
   background: gray;
   padding: 5px 20px;
   color: white;
   border-radius: 50px;
}
input{
  margin: 7px;
  box-sizing: border-box;
}
</style>
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?