テーブルにボタンを設置する方法

どれもDOM操作で無理矢理やっているので
kintoneのアップデートで使えなくなる可能性があります。

*******の部分は実際のフィールドIDに書き換える必要あり。

  • 余白にボタンを置く

(() => {
    // テーブルの特定の列にボタンを追加する関数
    const addButtonToDateField = (row) => {
        // フィールドIDを指定して、対象列の要素を取得(対象列が日付フィールドの場合)
        const targetField = row.querySelector('.control-date-field-gaia.field-*******');
        
        // 対象列が存在し、ボタンがまだ追加されていない場合
        if (targetField && !targetField.querySelector('.button')) {
            // ボタンを作成
            const button = document.createElement("button");
            button.innerText = "ボタン"; // ボタンに表示するテキスト
            button.className = `button`;
            
            button.onclick = () => {
                // ここにボタンクリック時の処理を書く
            };
            
            // ボタンを対象列に追加
            targetField.appendChild(button);
        }
    };

    // すべての行にボタンを追加する関数
    const addButtonsToAllRows = () => {
        // フィールドIDを指定して、対象テーブルの要素を取得
        const tableEl = document.querySelector(".subtable-gaia.subtable-*******.edit-subtable-gaia");
        const rows = tableEl?.querySelectorAll("tr"); // 行を取得
        
        // 行が存在しない場合は終了
        if (!rows) return;
        
        // 一行目を除くすべての行にボタンを追加
        for (let i = 1; i < rows.length; i++) {
            addButtonToDateField(rows[i]);
        }
    };

    // ボタンを追加するイベントハンドラ
    const addButtons = (event) => {
        addButtonsToAllRows();
        return event;
    };

    // レコードの編集画面または追加画面が表示された時にボタンを追加
    kintone.events.on(['app.record.edit.show', 'app.record.create.show'], addButtons);
    
    // テーブルの行が増えたときにボタンを追加
    kintone.events.on(['app.record.edit.change.テーブル', 'app.record.create.change.テーブル'], (event) => {
        addButtons(event);
        return event;
    });
})();
「いいね!」 4
  • テキストボックス内にボタンを置く

(() => {
    // テーブルの特定の列にボタンを追加する関数
    const addButtonToDateField = (row) => {
        // フィールドIDを指定して、対象列の要素を取得(対象列が文字列1行フィールドの場合)
        const targetField = row.querySelector('.control-single_line_text-field-gaia.field-*******');
        
        // 対象列が存在し、ボタンがまだ追加されていない場合に処理する
        if (targetField && !targetField.querySelector('.canvas-button')) {
            // テキストボックスを取得(対象列が文字列1行フィールドの場合)
            const inputContainer = targetField.querySelector('.input-text-outer-cybozu');

            // ボタンの要素を作成
            const canvas = document.createElement("canvas");
            canvas.className = "canvas-button";
            canvas.width = 30;
            canvas.height = 30;
            canvas.style.position = 'absolute';
            canvas.style.right = '5px'; // テキストボックスの右に配置
            canvas.style.top = '50%'; // テキストボックスのY軸中央に配置
            canvas.style.transform = 'translateY(-50%)'; // 縦方向の中央揃え
            canvas.style.cursor = "pointer";

            const ctx = canvas.getContext("2d");

            // ボタンの背景を描画
            const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height); // 縦方向にグラデーション
            gradient.addColorStop(0, "#4CAF50"); // 上部の色
            gradient.addColorStop(1, "#388E3C"); // 下部の色
            ctx.fillStyle = gradient;
            ctx.beginPath();
            ctx.arc(canvas.width / 2, canvas.height / 2, 12, 0, Math.PI * 2, true); // 円形を描画
            ctx.fill();

            // シャドウを設定
            ctx.shadowColor = "rgba(0, 0, 0, 0.3)";
            ctx.shadowBlur = 5;
            ctx.shadowOffsetX = 2;
            ctx.shadowOffsetY = 2;

            // 上記背景内に白いチェックマークを描画
            ctx.fillStyle = "#FFFFFF";
            ctx.beginPath();
            ctx.moveTo(10, 15); // チェックマークの始点
            ctx.lineTo(13, 18); // チェックマークの中点
            ctx.lineTo(20, 10); // チェックマークの終点
            ctx.lineWidth = 2;
            ctx.strokeStyle = "#FFFFFF"; // 線の色
            ctx.stroke();
            ctx.closePath();

            canvas.onclick = () => {
                // ここにボタンクリック時の処理を書く
            };

            // テキストボックスの親要素にボタンを追加
            inputContainer.style.position = 'relative'; // 親要素を相対位置に設定
            inputContainer.appendChild(canvas);
        }
    };

    // すべての行にボタンを追加する関数
    const addButtonsToAllRows = () => {
        // フィールドIDを指定して、対象テーブルの要素を取得
        const tableEl = document.querySelector(".subtable-gaia.subtable-*******.edit-subtable-gaia");
        const rows = tableEl?.querySelectorAll("tr"); // 行を取得
        
        // 行が存在しない場合は終了
        if (!rows) return;
        
        // 一行目を除くすべての行にボタンを追加
        for (let i = 1; i < rows.length; i++) {
            addButtonToDateField(rows[i]);
        }
    };

    // ボタンを追加するイベントハンドラ
    const addButtons = (event) => {
        addButtonsToAllRows();
        return event;
    };

    // レコード編集画面または追加画面が表示された時にボタンを追加
    kintone.events.on(['app.record.edit.show', 'app.record.create.show'], addButtons);

    // テーブルの行が増えたときにボタンを追加
    kintone.events.on(['app.record.edit.change.テーブル', 'app.record.create.change.テーブル'], (event) => {
        addButtons(event);
        return event;
    });
})();
「いいね!」 2
  • テーブルからデフォルトの行削除ボタンを消して
    代わりにCanvasで描いた行削除ボタンを置き
    値が入力済の行を削除しようとしたとき確認を取る

CSS

/* デフォルトの行削除ボタンを非表示にする */
.remove-row-image-gaia {
    display: none !important;
}

JavaScript

(() => {
    'use strict';

    kintone.events.on([
        'app.record.create.change.テーブル',
        'app.record.edit.change.テーブル',
        'app.record.edit.show'
    ], (event) => {

        const updateCanvasButtons = () => {
            const rows = document.querySelectorAll('.subtable-gaia tbody tr'); // テーブルの行を取得
            rows.forEach((row, index) => {
                // 行が2行以上ある場合、各行にCanvasでボタンを設置
                if (rows.length > 1 && !row.querySelector('.canvas-delete-button')) {
                    const canvas = document.createElement('canvas');
                    canvas.className = 'canvas-delete-button';
                    canvas.width = 40;
                    canvas.height = 40;

                    const context = canvas.getContext('2d');
                    
                    // ボタンを描画する関数
                    const drawButton = (fillStyle) => {
                        context.clearRect(0, 0, canvas.width, canvas.height);
                        context.beginPath();
                        context.arc(canvas.width / 2, canvas.height / 2 + 10, 9, 0, Math.PI * 2, false); // 円を描画
                        context.fillStyle = fillStyle; // 塗りつぶし色を設定
                        context.fill(); // 上記の色で塗りつぶしを実行
                        context.closePath();
                        context.fillStyle = '#fff'; // テキスト色を白に設定
                        context.font = '16px Arial';
                        context.textAlign = 'center'; // テキストの配置を中央に設定
                        context.textBaseline = 'middle';
                        context.fillText('−', canvas.width / 2, canvas.height / 2 + 10); // テキストを描画
                    };

                    drawButton('#ccc'); // 初期状態のボタンを描画

                    // マウスオーバーイベント
                    canvas.addEventListener('mouseover', () => drawButton('#ff3d3d'));
                    // マウスアウトイベント
                    canvas.addEventListener('mouseout', () => drawButton('#ccc'));
                    // クリックイベント
                    canvas.addEventListener('click', () => {
                        const record = kintone.app.record.get(); // 現在のレコードを取得
                        const tableRecords = record.record.テーブル.value[index].value; // Canvasボタンが押された行の値を取得
                        const fields = ["文字列1行", "文字列複数行", "日付", "ドロップダウン"]; // フィールドコードの配列
                        
                        // 上記フィールドに値が存在するか確認
                        const hasValue = fields.some(field => tableRecords[field]?.value) ||
                            // 添付ファイルの有無を確認
                            row.querySelector('.control-file-field-gaia .plupload_file_name');

                        // 値か添付ファイルが存在する場合の確認
                        if (hasValue && !confirm('この行には値が入力されていますが、本当に削除しますか?')) return;

                        // デフォルトの行削除ボタンのクリックイベントを呼び出す
                        row.querySelector('.remove-row-image-gaia').click();
                    });

                    // デフォルトの行削除ボタンがあった所にCanvasで描いたボタンを追加
                    row.querySelector('.subtable-operation-gaia').appendChild(canvas);
                } 
                // 行が1行しかない場合はボタンを追加しない
                else if (rows.length === 1 && row.querySelector('.canvas-delete-button')) {
                    row.querySelector('.canvas-delete-button').remove();
                }
            });
        };

        updateCanvasButtons();

        // 行追加ボタンにイベントリスナーを追加
        document.querySelector('.add-row-image-gaia')?.addEventListener('click', updateCanvasButtons);
        
        // テーブルの変更を監視
        new MutationObserver(updateCanvasButtons).observe(document.querySelector('.subtable-gaia tbody'), { childList: true });

        return event;
    });
})();
「いいね!」 2
  • ヘッダにボタンを設置し、ボタンクリック時は
    全ての行のボタン設置列に対して一括処理をする

(() => {
    'use strict';

    // レコード追加画面か編集画面を表示したときのイベント
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], () => {
        // テーブルの要素を取得
        const subtable = document.querySelector('.subtable-row-gaia .subtable-gaia');
        
        if (subtable) {
            // テーブルのヘッダからフィールド名(フィールドコードではない)が「数値」のセルを探す
            const numericsHeader = Array.from(subtable.querySelectorAll('th')).find(th => {
                const label = th.querySelector('.subtable-label-inner-gaia');
                return label && label.innerText === '数値';
            });

            if (numericsHeader) {
                // ボタン追加によって数値列の横幅が変わらないように最小幅を設定
                numericsHeader.style.minWidth = '193px';

                // ボタンを作成
                const button = document.createElement('button');
                button.innerText = '行番号一括設定';
                button.style.color = '#767676';
                button.style.marginLeft = '-109px';

                // ボタンのフォントサイズをヘッダに合わせる
                const numericsLabel = numericsHeader.querySelector('.subtable-label-inner-gaia');
                if (numericsLabel) {
                    const fontSize = window.getComputedStyle(numericsLabel).fontSize;
                    button.style.fontSize = fontSize;
                }

                // ボタンをクリックしたときの処理
                button.addEventListener('click', () => {
                    // 現在のレコードから[テーブル]各行の行番号を取得
                    const record = kintone.app.record.get();
                    const table = record.record['テーブル'].value;

                    // 各行の[数値]に行番号を設定
                    table.forEach((row, index) => {
                        row.value['数値'].value = index + 1;
                    });

                    // 設定を反映
                    kintone.app.record.set(record);
                });

                // ヘッダの数値列にボタンを追加
                numericsHeader.appendChild(button);
            }
        }
    });
})();
「いいね!」 4

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。