お世話になっております。
7月よりトヨクモ株式会社へポケモンマスターとして入社しました武井と申します。
最近の悩みは、徒歩通勤のせいで永遠に生卵のストックが減らないことです。
さて、それ以上にkintoneユーザーを悩ませることがあるクセモノ「ルックアップ」。
今回取り上げるのは、「ルックアップフィールドのchangeイベントが効かない件」です。
前回記事はこちら→kintoneのルックアップでは自動「クリア」ができない
問題の諸相
通常の文字列フィールドや数値フィールドなどであれば、
「app.record.edit.change.フィールドコード」などとイベントを指定することで、その値が変更された瞬間――正確には変更され、エンターキーが押下されるか、マウスのフォーカスが外れたタイミング――にイベントを発生させられます。
他にもchangeイベントが効かないフィールドはあるようですが、取り分けルックアップは痛い。
何故ならよく使われるから。
よく使われるから、ルックアップに対するカスタマイズが入る可能性もまた高いのです。
こんな時に問題になる
本問題が首をもたげる例を挙げます。
以前、例で使用した「従業員マスタ」アプリ(ルックアップコピー元)と「給与」アプリ(ルックアップコピー先)を再度例にとります。
【おさらい】
「従業員マスタ」アプリ:「ID」、「氏名」の各フィールドを持つ
「給与」アプリ:「ID」(ルックアップ)、「氏名」(ルックアップコピー)、「日付」、「給与」の各フィールドを持つ
「役職」アプリ:「ID」(ルックアップ)、「氏名」(ルックアップコピー)、「役職」の各フィールドを持つ
以下のようなリレーションとなっています。
顧客から、以下のような新規要件が出て来ました。
「給与レコード作成時、給与欄にその人の役職によった所定の数値をデフォルトセットしたい」
SIerは「IDのchangeイベントで選択されたIDをキーにして役職を見に行けばOKやな!余裕っすw」と快諾しました。
SIerが帰社して早速改修してみると
「なぜや!うまくいかん!特にエラーも出てへんのに!イベント自体が発生してない!」
その後、SIerはデベロッパーサイトで、ルックアップはchangeイベントに対応していないことを知り、途方に暮れるのでした。
問題解決の道標
上記のような要件はよくあります。
しかし、kintoneではカスタマイズが必須となります。
私のスタンスは、今までの問題もこれから発信する問題もすべてカスタマイズなしで解決できることがベストだと思っています。
とはいえ、現状で出来ないものは仕方ないので、カスタマイズで解決できないか模索してみます。
解決策として考えられるのは以下の2手段です。
■コピーフック
環境さえ許容してくれるのであれば最も単純に解決できる手法です。
ルックアップフィールドそのものでは機能しないchangeイベントも、
コピーフィールドのchangeイベントは動作します。
ただし、この方法には2点の罠が潜んでいますので注意を要します。
- コピーフィールドが必須になってしまう。
- コピーフィールドが同じ内容の場合、機能しない。
1.は当然、コピーフィールドでフックするので、必須となります。
しかし、世の中には「コピーフィールドを伴わないルックアップ」というものが多数存在しております。
この場合、コピーフックの手法を使用する場合に「無駄なコピーフィールドを作成しなければならない」というデメリットが出て来てしまいます。
無駄なコピーフィールドを作成しなければならない場合、何がまずいかと言えば、「見た目がよろしくない」点と「データ管理上よろしくない」点が挙げられます。
「見た目」についてはカスタマイズで頑張れば糊塗できますが、不要なフィールドのためにカスタマイズするという状況に陥ってしまいます。
「データ管理」についても、フィールドを「見た目上」消せたとしても、コピーフィールドのデータ自体はアプリに残ってしまいますから、アプリのビューでカラムを「すべて表示」にした時などは、表示されてしまうことになります。
2.について、例えば「ID=0001」の「氏名=長宗我部国親」さんと、「ID=0003」の「氏名=長宗我部国親」さんが、
偶然、同姓同名で存在した場合、ルックアップで「0001→0003」へ変更したとしても、changeイベントは発火しません。
すなわち、「コピーフック」で用いる「コピーフィールド」は【一意性制約かつNOT NULL制約に即したフィールド】でなければならないのです。
まとめます。
- コピーフィールドが既にある
- しかもそのコピーフィールドのコピー元は一意でNOT NULLである
上記に合致する環境である場合にのみ、コピーフックは有効な手段となり得ます。
■自作イベントでフック
上記に比べると環境によりけりでしんどいと思われます。
単純にルックアップフィールドにjQueryのchangeイベントなどを設定しても、
拾えるのは手入力した場合の値変更のみで、取得ボタンを押して、一覧から選択した場合には発火しません。
この方法、細かいことを考えると途方もないため、
「一覧画面から選択した場合にのみイベント発火」として考えます。
(ルックアップの手入力不可とします)
(function () { "use strict"; kintone.events.on('app.record.create.show', function (event) { // ルックアップ手入力不可 $(".component-app-lookup-inputlookup .input-text-cybozu").attr("disabled", "disabled"); // ルックアップの監視開始 lookupCheck(); return event; }); // ルックアップの監視関数 function lookupCheck() { var lookupInterval = setInterval(function () { if ($("[class='button-simple-cybozu']").length > 0) { clearInterval(lookupInterval); var oneTimeFlg = true; $("[class='button-simple-cybozu']").on('click', function () { if (oneTimeFlg) { console.log(); var rec = kintone.app.record.get(); var id = rec.record.id.value; // 役職アプリのアプリID = 1415とする kintone.api('/k/v1/records', 'GET', {app: 1415, query: 'id = "' + id + '"'}, function (resp) { var position = resp.records[0].position.value; switch (position) { case "信濃守" : rec.record.salary.value = '100'; kintone.app.record.set(rec); break; case "土佐守護" : rec.record.salary.value = '200'; kintone.app.record.set(rec); break; case "関白" : rec.record.salary.value = '500'; kintone.app.record.set(rec); break; case "銀河総督" : rec.record.salary.value = '80000000000000'; kintone.app.record.set(rec); break; default : rec.record.salary.value = '10'; kintone.app.record.set(rec); break; } oneTimeFlg = false; lookupCheck(); }); } }); } }, 300); } })();
役職「信濃守」の給与が自動的に入力されましたッ……!!
さらに、そのままの状態で、偶然にも同姓同名であるもう一人の長宗我部国親さんを選択すると……
同姓同名の長宗我部国親さん(銀河総督)も問題なく固定給与が反映されています!!
この問題については、かなり環境によって対応しなければならない方法が変わってくる&複雑化すると思いますので、
やはり、根本的にkintoneというプラットフォームで対応していただきたい問題です。
以上、元kintone SIerでありながら、kintoneカスタマイズゼロを標榜するブログでした。