【Handsontable】確定ボタンのチェック処理


はじめに

これは、Handsontable Advent Calendar 2018の16日目の記事となります。

前回「【Handsontable】最大文字数制限(MaxLength)」では最大文字数制限を行いました、今回は確定ボタンのチェック処理を実装していきます。


確定ボタンのチェック処理

確定ボタンのチェック処理では、複数列セルのバリデーションを順次実行するようにします。そのため非同期処理を操作する Promise を利用しています。エラーは catch で一括チェックするようにしました。

※IE11対応をするため、await は使用しませんでした。

必須チェックをした際、必須項目が入力されていないところは赤くなりました。

validateCells メソッドでは全てのセルのバリデージョンを明示的に実行します。

全てのセルを対象とするため、エラー箇所は全て赤くなります。

全てエラー.png

1箇所でもバリデージョンエラーがあった場合、バリデージョンエラーの位置を getCellMeta(i, j).valid を使用して特定し必須項目または値の不正エラーメッセージを表示します。

必須項目エラー.png

次は主キーである商品コードが重複していないかをチェックします。

重複エラー.png

全てのエラーがなくなった場合、更新の確認メッセージを表示します。

商品マスタ保存.png

// チェック処理

function check() {
// 全入力項目チェック
var checkAllItem = function () {
return new Promise(function (resolve, reject) {
hot.validateCells(function (valid) {
if (valid) {
resolve();
} else {
result = { msg: 'All', row: 0, col: 0 };
reject(result);
}
});
});
}

// 重複チェック
var checkDuplicate = function () {
const colPrimaryKey = 2;

return new Promise(function (resolve, reject) {
var isDuplicate = false;
result = { msg: 'Duplicate', row: 0, col: colPrimaryKey };

for (var i = 0; i < hot.countRows(); i++) {
var key = hot.getDataAtCell(i, colPrimaryKey);
if (key == 0) continue;
for (var j = 0; j < hot.countRows(); j++) {
if (i != j) {
if (key === hot.getDataAtCell(j, colPrimaryKey)) {
result.row = j;
isDuplicate = true;
break;
}
}
}
if (isDuplicate) break;
}

if (!isDuplicate) {
resolve();
} else {
reject(result);
}
});
}

// 非同期チェック処理
var promise = Promise.resolve();

promise
.then(checkAllItem)
.then(checkDuplicate)
.then(function () {
var result = window.confirm('商品マスタを更新します。よろしいですか?');

if (result) {
console.log('保存処理');
}
else {
console.log('キャンセル');
}
return

}).catch(function (result) {
var isValid = true;
var errorMsg = '';

switch (result.msg) {
case 'All':
setError(result);
errorMsg = result.msg;
break;
case 'Duplicate':
errorMsg = "重複しています。";
break;
}

// エラーセルのフォーカスをセット
hot.selectCell(result.row, result.col);
// エラー表示
alert(errorMsg);
});
}

// エラーセット
function setError(obj) {
var headers = hot.getColHeader();

for (var i = 0; i < hot.countRows(); i++) {
for (var j = 2; j < hot.countCols(); j++) {
var isValid = hot.getCellMeta(i, j).valid;
if (isValid === false) {
obj.row = i;
obj.col = j;

var value = hot.getDataAtCell(i, j);
obj.msg = headers[j];
if (value === null || value.trim() === '') {
obj.msg += "は、必須項目です。";;
}
else {
obj.msg += "は、不正な値です。";
}
return;
}
}
}
}


データ保存処理

AjaxのPostを使用してサーバー側処理(ASP.NET)にJSON形式のデータを送信します。

今回はサーバー側処理の実装は省略します。

本来はデータ読込処理もサーバー側処理(ASP.NET)にする必要があります。

// POST用非同期処理

function postAjax(method, data, callback) {
$.ajax({
url: method,
type: 'POST',
dataType: 'json',
data: data,
contentType: 'application/json; charset=utf-8',
async: true,
processData: true,
cache: false
}).fail(function (xhr, status, error) {
alert(error);
}).done(function (data) {
callback(data);
});
}

// データ保存
function saveData() {
var process = function (data) {
if (data.success)
alert("保存しました。");
}
postAjax('SetProductMasterData', JSON.stringify(hot.getSourceData()), process);
}