注文書のようなアプリで明細行をテーブルで作成して、詳細画面にてExcelライクに入力するサンプルコードです。
Wijmoのトライアル版をこちらからダウンロードして、「JavaScript / CSSでカスタマイズ」に追加します。
- wijmo.min.js
- wijmo.grid.min.js
- wijmo.culture.ja.min.js
サンプルコードではunderscore.jsを利用していますので下記も追加します。
サンプルコード
(function() {
"use strict";
kintone.events.on(["app.record.edit.show","app.record.create.show"], function(e) {
var record = e.record;
// 明細をFlexgridに表示
showContent(record["明細"].value);
// 標準の明細を隠す
kintone.app.record.setFieldShown("明細", false);
return e;
});
var columnTypes;
/**
* KintoneデータをFrexgridに表示します
* @param {Object} records
*/
var showContent = function (records) {
columnTypes = getColumnTypes(records);
var dataList = convertToArray(records);
var cv = new wijmo.collections.CollectionView(dataList);
var grid;
// FlexGridを生成
var gridSpace = kintone.app.record.getSpaceElement("flexgrid");
if (_.isEmpty(gridSpace.innerHTML)) {
grid = new wijmo.grid.FlexGrid(gridSpace);
grid.initialize({
autoGenerateColumns: false,
itemsSource: cv,
allowAddNew: true,
allowSorting: false,
allowDelete: true,
imeEnabled: true,
columns: [{
binding: 'id',
visible: false,
}, {
binding: '内容',
width: 200,
}, {
binding: '規格',
width: 200,
}, {
binding: '単価',
}, {
binding: '数量',
width: 80,
}, {
binding: '金額',
isReadOnly: true,
}],
});
// セル編集が確定またはキャンセルされたとき
grid.cellEditEnded.addHandler(function (sender, event) {
// 金額を計算する。
var column = sender.columns[event.col];
if (column.binding == "数量" || column.binding == "単価") {
calcAmount(sender, event.row);
updateContent(sender);
}
});
// 行が追加されたとき
grid.rowAdded.addHandler(function (sender, event) {
updateContent(sender);
});
// 行が削除されたとき
grid.deletedRow.addHandler(function (sender, event) {
updateContent(sender);
});
// セルにペーストしたとき
grid.pastedCell.addHandler(function (sender, event) {
var fromRow = event.range.row;
var toRow = event.range.row2;
for (var row = fromRow; row <= toRow; row ++) {
calcAmount(sender, row);
}
updateContent(sender);
});
} else {
grid = wijmo.Control.getControl(gridSpace);
grid.itemsSource = cv;
}
};
/**
* Flexgridの内容をKintoneのrecordに反映します
*/
var updateContent = function(grid) {
var dataList = grid.itemsSource.items;
var items = [];
for (var i = 0; i < dataList.length; i ++) {
var item = {};
item.value = {};
if (!_.isEmpty(dataList[i].id)) {
item.id = dataList[i].id;
}
for (var key in columnTypes) {
item.value[key] = {};
var value = null;
if (_.has(dataList[i], key)) {
value = dataList[i][key];
}
// isEmpty(1)がtrue判定されるのでisNullで判定している
if (_.isNull(value)) {
// 未入力エラーを回避する
if (columnTypes[key] == "NUMBER" || columnTypes[key] == "CALC") {
value = 0;
} else {
value = "";
}
}
item.value[key].value = value;
item.value[key].type = columnTypes[key];
}
items.push(item);
}
var record = kintone.app.record.get();
record.record["明細"].value = items;
kintone.app.record.set(record);
};
/**
* 金額を計算します
* @param {Object} grid FlexGrid
* @param {Number} row 行インデックス
*/
var calcAmount = function (grid, row) {
var quantity = 0; // 数量
var tanka = 0; // 単価
var value;
value = grid.getCellData(row, grid.columns.indexOf("数量"), false);
if (!_.isNull(value) && !_.isUndefined(value)) {
quantity = value;
}
value = grid.getCellData(row, grid.columns.indexOf("単価"), false);
if (!_.isNull(value) && !_.isUndefined(value)) {
tanka = value;
}
var amount = Math.floor(tanka * quantity);
grid.setCellData(row, grid.columns.indexOf("金額"), amount);
};
/**
* FlexgridカラムのKintoneのデータタイプ情報を取得します。
* @param {Object} kintoneのtype-value型のレコード
* @returns {Object} Key-Valueハッシュ
*/
var getColumnTypes = function (records) {
var columnTypes = {};
if (records.length > 0) {
for (var key in records[0].value) {
columnTypes[key] = records[0].value[key].type;
}
}
return columnTypes;
};
/**
* kintoneのtype-value型のレコードをFlexgrid用のオブジェクト配列に変換
* @param {Object} kintoneのtype-value型のレコード
* @returns {Object} 変換後の配列
*/
var convertToArray = function (records) {
var datas = [];
for (var i = 0; i < records.length; i++) {
var data = {};
data.id = records[i].id;
for (var key in records[i].value) {
if (records[i].value[key].type === 'NUMBER' || records[i].value[key].type === 'CALC') {
data[key] = Number(records[i].value[key].value);
} else {
data[key] = records[i].value[key].value;
}
}
datas.push(data);
}
return datas;
};
})();