5
4

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 5 years have passed since last update.

ag-Gridでセルをドラッグ&ドロップ

Posted at

先日ag-Gridのセルをドラッグ&ドロップで移動させる機会がありました。
その際、あまり処理の実装例が無くて困ったので調べた内容をまとめました。

最近Vue.jsの勉強をしているのでVue.jsで書いてますが普通のJavaScriptでも可能と思います。

コード

ポイントっぽいところにコメントを記載しています。

src/agdragcelldrag.vue
<template>
    <ag-grid-vue style="width: 500px; height: 500px;"
        class="ag-theme-balham"
        :enable-col-resize="false"
        :column-defs="columnDefs"
        :row-data="rowData"
        :grid-ready="onGridReady"
        :process-row-post-create="onProcessRowPostCreate">
    </ag-grid-vue>
</template>

<script>
import {AgGridVue} from "ag-grid-vue";

export default {
    name: 'App',
    data() {
        return {
            // ag-GridのAPI
            gridApi: null,
            // 列定義
            columnDefs: null,
            // データ
            rowData: null,
            // ドラッグ開始位置
            dragStartPosition: null
        }
    },
    components: {
        AgGridVue
    },
    beforeMount() {
        // 列とデータの初期化
        this.columnDefs = [
            {headerName: 'Make', field: 'make'},
            {headerName: 'Model', field: 'model'},
            {headerName: 'Price', field: 'price'}
        ];
        this.rowData = [
            {make: 'Toyota', model: 'Celica', price: 35000},
            {make: 'Ford', model: 'Mondeo', price: 32000},
            {make: 'Porsche', model: 'Boxter', price: 72000}
        ];
    },
    methods: {
        onGridReady(params) {
            // ag-Gridへデータをセット
            this.gridApi = params.api;
            this.columnApi = params.columnApi;
        },
        onProcessRowPostCreate(params) {
            // ドラッグイベントを全てのセルへセット
            Array.prototype.forEach.call(params.eRow.children, item => {
                item.draggable=true
                item.ondragstart=this.onDragStart
                item.ondragover=this.onDragOver
                item.ondrop=this.onDrop
            });
        },
        onDragStart(event) {
            // ドラッグ開始イベント
            // ドラッグが開始されたHTMLエレメントから行IDと列IDを取得する
            var colId = event.target.getAttribute('col-id')
            var rowId = event.target.parentElement.getAttribute('row-id')

            // セルが空の場合はドラッグさせない
            if (!this.rowData[rowId][colId]) {
                event.preventDefault()
            }

            // ドラッグ開始位置を保持しておく
            this.dragStartPosition = {row: rowId, col: colId}
        },
        onDragOver(event) {
            // 別の要素へドラッグされたイベント
            // ドラッグを許可する
            event.preventDefault()
        },
        onDrop(event) {
            // ドラッグ可能エリアへドロップされたイベント
            // ドロップ位置の行IDと列IDを取得する
            var colId = event.target.getAttribute('col-id')
            var rowId = event.target.parentElement.getAttribute('row-id')

            // ドラッグ開始位置を取得する
            var from = this.dragStartPosition

            // データを入れ替える
            var tmp = this.rowData[rowId][colId]
            this.rowData[rowId][colId] = this.rowData[from.row][from.col]
            this.rowData[from.row][from.col] = tmp

            // 表示を更新する
            this.gridApi.refreshCells({})
        },
    }
}
</script>

デモ

ポイントはドラッグイベントおよびドロップイベント発生時に行IDと列IDを取得しているあたりです。
取得したIDを元にグリッドにセットされた生データを編集しています。
また、jsで直接データを弄っただけでは表示に反映されないため、ag-GridのAPIを呼んで更新処理を実行しています。

git

参考

5
4
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
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?