Handsontable のレスポンス改善

記事の概要

Handsontable でセルに入力された値と、元々セルにロードしてある値を元に計算して結果を別のセルに反映するというような処理を書いたのだが、最初に書いたコードではレスポンスが悪すぎて使い物にならなかったので改善したよという話。

そもそもどういうコードを書いたのか

あんまり詳しく書くと守秘義務がアレなのでボカして書きますが、前年度の売り上げと会社の営業日数、それと今年度の営業日数のデータが既にロードされており、そこに今年度の売り上げ目標を入力すると、前年度比(単純に前年度との比較)と実質前年度比(営業日数差を加味した値)が計算されて、さらに上期、下期、年度での数値も計算するという処理を書きました。

最初に書いたコードは getDataAtCell で入力があった月の各データを取得して計算、結果を対象のセルに setDataAtCell で書き込むという教科書通りの内容でしたが、上述の通りこれのレスポンスが悪すぎてどうにもなりませんでした。

どうやら個々のセルに対していちいち setDataAtCell をかけると、グリッドへの値の書き込みとブラウザでのレンダリングを書き込むセルの回数繰り返してしまうためレスポンスが極端に悪くなるようです。

じゃぁどうコードを書けばいいのよ

結論から言うと getSourceData でグリッドにロードされているデータのオブジェクトを取得し、そのオブジェクトに計算結果を適用してから loadData で読み込めば OK です。これならグリッドへの値の書き込みもブラウザにレンダリングさせる回数も1回で済みます。

ただし loadData を使うのでセル設定などはロード直後の状態に戻ってしまうので、特定のセルに setCellMeta などしている場合は再度同じ設定をかけてあげる必要があります。またグリッドがソートされている場合は isSorted で条件を分岐した上で

  • toPhysicalRow や toPhysicalColumn を使って表示されているグリッドのセル座標を実際のデータのセル座標に変換して処理する

  • getSortConfig して loadData の後で setSortConfig する

といったケアが必要なので注意してください。

あと loadData だと addHookOnce で afterLoadData を指定して、その中で promise を resolve するようにすればデータロード完了のタイミングが取れるので便利です。フックを設定するにしても afterSetDataAtCell だと最後の setDataAtcell だとの判断が必要になるのでちょっと手間かかるからね。

#JavaScript #Handsontable

この記事が気に入ったらサポートをしてみませんか?