前回、
Handsontable
を使って、Excelのように入力ができるようなTipsを公開しました。
今回は、前回の閲覧・編集に加えて、レコードの追加・削除にも対応したいと思います。
前回記事
のコードをベースに修正していきますので前回記事も参照ください。
また、コードは、
GitHub mura-/kintone_handsontable.js
に公開しています。
基本的に上記をコピーして必要な部分を書き換えれば動くとは思いますが、必要に応じてコードを参照しながら下記をお読みください。
viewIdはカスタマイズビュー設定時のviewIdを入力してください。
デモ環境
で実際に動作を確認できます。
ログイン情報は
cybozu developer networkデモ環境
で確認してください。
サンプルアプリの設定
固定リンクがコピーされました
前回と同様のアプリ設定を用います。
前回記事の
「kintoneカスタマイズでの導入方法 - サンプルアプリの準備」
の項目を参考にしてください。
レコードの追加に対応する
固定リンクがコピーされました
前回のsaveRecordsメソッドを拡張し、追加・更新両方に対応します。
今回は、追加・更新のために
bulkRequest
を利用しました。
bulkRequestは、本来複数アプリへのレコード一括処理をするためにありますが、もちろん同じアプリにも使えます。
これを使うことで1回のAPIの呼び出しだけでkintoneのレコード更新が済みますし、なにより追加・更新処理どちらかでエラーが有った場合はロールバックされるので安全です。
引数には、kintoneのレコードデータ(records)と、Handsontable上でセルが編集された際に取得できる配列(changeDatas)を指定することとします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
// kintoneのレコード更新、追加用メソッド
const saveRecords = (records, changedDatas, callback, errorCallback) =>{
const requests = [];
const updateRecords = [];
const insertRecords = [];
let changedRows = [];
// 変更されたセルの配列から、変更があった行だけ抜き出す
for (let i = 0; i < changedDatas.length; i++) {
changedRows.push(changedDatas[i][0]);
}
// 変更があった行番号の重複を排除
changedRows = changedRows.filter((x, i, self) => {
return self.indexOf(x) === i;
});
// 変更があった行から、レコード追加か変更かを判断し、クエリをつくる
for (let i = 0; i < changedRows.length; i++) {
if (records[changedRows[i]]['レコード番号'].value === null) {
insertRecords.push(
setParams(records[changedRows[i]])
);
} else {
updateRecords.push({
id: records[changedRows[i]]['レコード番号'].value,
record: setParams(records[changedRows[i]])
});
}
}
// 更新用bulkRequest
requests.push({
method: 'PUT',
api: '/k/v1/records.json',
payload: {
app: kintone.app.getId(),
records: updateRecords
}
});
// 追加用bulkRequest
requests.push({
method: 'POST',
api: '/k/v1/records.json',
payload: {
app: kintone.app.getId(),
records: insertRecords
}
});
// bulkrequestで一括で追加、更新。
// 失敗した場合はロールバックされる。
kintone.api('/k/v1/bulkRequest', 'POST', {requests: requests},
(resp) => {
console.dir(requests);
console.dir(resp);
callback(resp);
},
(resp) => {
errorCallback(resp);
}
);
};
|
レコードの削除に対応する
固定リンクがコピーされました
handsontableの設定
削除は、コンテキストメニュー(右クリックメニュー)から実行できるようにしたいと思います。
まず、handsontableのコンテキストメニューオプションを設定します。
デフォルトで機能はたくさんあるのですが、今回は行削除(remove_row)だけに対応します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
// handsontable初期化
hot = new Handsontable(container, {
// この時点ではdataは入力せず、あとから読み込ませるようにする。(データ更新時も再読み込みさせたいため)
data: [],
// 空白行
minSpareRows: 10,
// 表示したいカラム
colHeaders: ['レコード番号', '会社名', '先方担当者名', '見込み時期', '確度', '製品名', '単価', 'ユーザー数', '小計'],
// コンテキストメニュー(右クリックメニュー)を指定。今回は削除用メニューのみ。
contextMenu: ['remove_row'],
// 必要に応じてreadOnlyの指定ができます。
columns: [
{data: 'レコード番号.value', readOnly: true},
{data: '会社名.value'},
{data: '先方担当者名.value'},
{data: '見込み時期.value'},
{data: '確度.value'},
{data: '製品名.value'},
{data: '単価.value'},
{data: 'ユーザー数.value'},
{data: '小計.value', readOnly: true}
],
// : 以下略
});
|
削除メソッドの作成
次に、削除用メソッド(deleteRecords)を作成します。
引数には、kintoneのレコードデータ(records)と、削除する行(index)・削除できる行数(amount)を指定できるようにします。
削除するべきレコード番号を抽出して、削除APIを呼び出します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// kintoneのレコード削除用メソッド
const deleteRecords = (records, index, amount, callback, errorCallback) => {
let i;
const ids = [];
for (i = index; i < index + amount; i++) {
ids.push(records[i]['レコード番号'].value);
}
kintone.api('/k/v1/records', 'DELETE', {app: kintone.app.getId(), ids: ids},
(resp) => {
callback(resp);
},
(resp) => {
errorCallback(resp);
}
);
};
|
削除メソッドの呼び出し
レコードを削除すると、HandsontableのbeforeRemoveRowイベントが発行します。
beforeRemoveRowイベントの中で、deleteRecordsメソッドを呼び出して、削除処理を行います。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
hot = new Handsontable(container, {
// : 省略
beforeRemoveRow: (index, amount) => {
// kintoneのレコードを削除する
deleteRecords(hot.getSourceData(), index, amount,
(deleteRecordsResp)=> {
console.dir(deleteRecordsResp);
getRecords((getRecordsResp)=> {
// 削除後、データを再読み込み
hot.loadData(getRecordsResp.records);
});
},
(resp)=> {
console.dir(resp);
}
);
},
// : 省略
});
|
データの乖離が起きないよう、追加・更新・削除のタイミングでデータを再同期します。
データ取得メソッドの作成
今回は特に検索条件を指定しませんが、次のように並び替えだけはレコード番号昇順にしてください。
降順だとレコードを追加した行が一番先頭に表示されてしまいます。
また、limitも500と指定することで500件まで表示できます。
1
2
3
4
5
6
7
8
9
10
11
|
// kintoneのレコード取得用メソッド
const getRecords = (callback, errorCallback) => {
kintone.api('/k/v1/records', 'GET', {app: kintone.app.getId(), query: 'order by レコード番号 asc limit 500'},
(resp) => {
callback(resp);
},
(resp) => {
errorCallback(resp);
}
);
};
|
追加・更新・削除時に同期する
次のように、追加・更新・削除時のcallbackメソッドに同期するメソッドを指定します。
HandsontableはloadDataメソッド
があり、引数に取得したkintoneレコードデータを指定することで再同期できます。
また、同期することにより、フォーム設定画面で指定したデフォルト値が表示されたり、計算フィールドのレコードが計算されて表示されるなどのメリットもあります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
hot = new Handsontable(container, {
// : 省略
afterChange: (change, source) => {
// kintoneのレコードを更新、追加する
saveRecords(hot.getSourceData(), change,
(resp)=> {
console.dir(resp);
getRecords((saveRecordsResp)=> {
// 更新後、データを再読み込み
hot.loadData(saveRecordsResp.records);
},
(getRecordResp)=> {
// レコード取得失敗時に呼び出される
console.dir(getRecordResp);
});
},
(resp)=> {
// 更新・追加時に呼び出される
console.dir(resp);
}
);
}
});
|
データを定期的に同期する
固定リンクがコピーされました
追加・更新・削除時だけでなく、長く画面を開いていればデータに乖離が起こる場合もあります。
そこで、今回はデータを定期的に同期する処理もいれてみました。
1
2
3
4
5
6
7
8
9
|
// 定期的にkintone上のデータを再取得する
const autoload = () =>{
getRecords((resp)=> {
hot.loadData(resp.records);
});
setTimeout(()=> {
autoload();
}, 10000); // 10秒。APIの呼び出し数の上限があるので、必要に応じて変更してください。
};
|
- 今回のコードにおいて表示できるデータ件数は500件まで、更新は100件までとなっています。コードをカスタマイズすることで、絞り込みやデータの条件を増やすことができます。
- 表示できるデータ件数に制限があるため、今回のサンプルは
一覧の設定
の「ページネーションを表示する」に対応していません。
- APIの呼び出し回数は1アプリ1日あたり上限10,000回です。今回は同期処理をいれていますが、必要に応じて同期間隔を遅くしてください。開きっぱなしに注意してください。
Excelライクな操作で前回の閲覧・編集に加えて、レコードの追加・削除ができるようになりました。
一括でデータを追加、更新したい場合や、削除したい場合に便利ですね。
Handsontable
を利用した
kintoneスプレッドシートプラグイン
を開発して公開もしています。
ぜひ活用ください。
次回は、
Handsontableを使ってkintoneをExcelライクに入力しよう その3 - 上級編
で、有償版のHandsontableでできることを紹介します。