はじめに
これは、Handsontable Advent Calendar 2018の9日目の記事となります。
前回は「【Handsontable】全選択/全解除チェックと行削除」では全選択/全解除チェックと行削除を行いました、今回は変更マークの付与と必須チェックを実装していきます。
変更マークの付与
先頭列(Edit)に同じ行のいずれかの列の変更があった場合に「*」を付ける。
但し、編集列と選択列は対象外とする。
Handsontableではデータの更新時、afterChangeオプションに指定したメソッドが呼び出される。
const EDIT_MARK = '*';
// changesには[[row, col, pretext, aftertext]] でセットされる。
afterChange: function (changes, source) {
if (source === 'loadData') return;
for (var i = 0; i < changes.length; i++) {
var change = changes[i];
// 編集と選択は対象外
if (change[1] === COL_EDIT || change[1] === COL_SELECT) continue;
// 変更前と変更後が同じは対象外
if (change[2] === change[3]) continue;
// 編集に"*"を付ける
hot.setDataAtCell(changes[0][0], 0, EDIT_MARK);
}
}
必須チェック
必須チェックする項目としては、商品コードと商品名と単価となります。
値をチェックするカラムに下記のvalidatorオプションを追加します。
validator: function (value, callback) { callback(true); }
var hot = new Handsontable(grid, {
columns: [
{ data: COL_EDIT, readOnly: true, type: 'text' },
{ data: COL_SELECT, type: 'checkbox' },
{ data: COL_PRODUCTCODE, type: 'text', width: 80, validator: function (value, callback) { callback(true); } },
{ data: COL_PRODUCTNAME, type: 'text', width: 200, className: "htLeft htMiddle", validator: function (value, callback) { callback(true); } },
{ data: COL_UNITPRICE, type: 'numeric', numericFormat: { pattern: '0,00', culture: 'ja-JP' }, validator: function (value, callback) { callback(true); } },
{ data: COL_COMMENT, type: 'text', width: 300, className: "htLeft htMiddle", validator: function (value, callback) { callback(true); } }
],
すると、afterValidateオプションに指定したメソッドが呼び出されます。
※カラムにvalidatorオプションが必要だったかちょっと分からなくなったのですが、ないとメソッドが呼ばれない。
【2018/12/16追記】過去の自分用のメモには下記のように書いてありました。
text入力で afterValidateでまとめて桁数チェックをしようとしたが、afterValidateが動作しない。
無理矢理、validatorを経由させることでafterValidateの処理に入ってくるようになった。
※IE11対応なのでアロー演算子は使用していない。
今回は、先頭列に編集マークがある場合のみ必須項目チェックを行います。
こうすることで新規行はチェックされないようになります。
※編集マークがなければ beforeValidateオプション でもいいと思う。
afterValidate: function (isValid, value, row, prop, source) {
// 既にエラーなら何もしない
if (!isValid) return false;
// 桁数チェック
switch (prop) {
case COL_PRODUCTCODE:
// 必須項目チェック
if (this.getDataAtCell(row, 0) === EDIT_MARK && (value === null || value.trim() === "")) return false;
// 桁数チェック
if (value !== null && value.length !== 5) return false;
break;
case COL_PRODUCTNAME:
// 必須項目チェック
if (this.getDataAtCell(row, 0) === EDIT_MARK && (value === null || value.trim() === "")) return false;
// 桁数チェック
if (value !== null && value.length > 30) return false;
break;
case COL_UNITPRICE:
// 必須項目チェック
if (this.getDataAtCell(row, 0) === EDIT_MARK && (value === null || value === "")) return false;
break;
case COL_COMMENT:
if (value !== null && value.length > 100) return false;
break;
}
return true;
}