こんにちは!炎のマネージャーの下で元気に働く新卒の平原です!
先日、「カウボーイビバップ」というアニメが好きだと先輩社員に話したら「サムライチャンプルーもおすすめ」と言われ、TSUTAYAでレンタルして観てみました。あまりにもカッコイイので侍にジョブチェンジしようか悩んでいます...。
今年も残りわずかですね。今年の1年間は皆様にとってどんな1年だったでしょうか?私にとっては本当に目まぐるしい、あっという間の1年でした。3月まで大学生だったのが遠い過去の出来事のようです。
入社しておよそ9ヶ月が経ちました。会社で私は主にApexでの開発、特に夏の間は当社製品であるSkyVisualEditorで画面作成をして、Apexで処理を追加するというようなことをひたすら行ってきました。
というわけで今回は、外出が多くて普段はあまり事務所にいらっしゃらないマネージャーに代わりまして、私の方から、開発始めたての頃に苦労したSkyVisualEditorでの作業を記事にしようと思います。SkyVisualEditorは簡単に画面の開発ができますが、行き詰まる部分もありましたのでそこをご紹介します。主にApexとJavaScriptによる拡張がメインです。よろしくお願いします!
やっていたこと
- SkyVisualEditor(以下SVE)でヘッダーと明細が見える画面を作る
- 明細のデータテーブルには空の選択リストを用意する
- 画面描画時に選択リストの設定値に、JavaScriptで取引先の項目名を設定する
この画面は「取引先項目名を使った検索条件を保存するための画面」で、保存した条件レコードは、別の画面で呼び出してSOQL文を作るためのものです。今回はこの画面の中で、動的に現在の取引先の項目を取得する処理で苦労した点をご紹介します。
Salesforce標準機能では難しいですが、SVEはApex処理を追加するExtenderクラスやJavaScriptで拡張することによって複雑な要件にも対応することが出来ます。 さらに画面レイアウトがノンコーディングで作れる分、処理の方に集中できるメリットもあります。具体的には
- Extenderに取引先項目名を取得するメソッドを用意
- JavaScriptで取得した項目名を選択リストに設定
という方法です。
↑画像は開発環境で作成したイメージです。保存ボタンを押すと、検索条件オブジェクトと検索条件明細オブジェクトが紐付いた状態で保存されます。
取引先項目getメソッド作成
取引先項目名を取得するためには、DescribeSObjectResultクラスを使います
public List<String> getAccountItems(){ List<String> strFieldKeys = new List<String>(); Schema.SObjectType sobjType = Schema.getGlobalDescribe().get('Account'); Map<String, Schema.SObjectField> fmap = sobjType.getDescribe().fields.getMap(); for (String fieldKey : fmap.keySet()) { Schema.SObjectField f = fmap.get(fieldKey); Schema.DescribeFieldResult fr = f.getDescribe(); strFieldKeys.add(fr.getLabel()); } strFieldKeys.sort(); return strFieldKeys; }
JavaScriptでメソッドを実行できない?!(勘違い)
上記のメソッドを実行すると、取引先の全項目のラベル名をリストで取得できます。次はSVEでJavaScriptからこのメソッドを呼び出すわけなのですが、この時私はgetterメソッドの使い方がわかっておらず、「JavaScriptではメソッドを呼び出せない」と勘違いして勝手に困っていました。今思い返すとただただ勉強不足だったなという感が否めません。
困った私はチームの先輩(サムライチャンプルーをおすすめしてくれた人)に相談し、以下のような打開策を伝授していただきました。
- getAccountItemsでリストを取得するのではなく、リストを区切り文字で数珠つなぎにした長い文字列にする
- Extenderのinit()メソッドをオーバーライドして初期処理の際にロングテキスト型の項目に文字列を挿入するロジックを作る
- ロングテキスト項目を画面に非表示にした状態で、jQueryで取得する
- 区切り文字でsplitして、リストで取得する
jQueryで取ってくることができるのはわかっていたので、とりあえずこれでJavaScript上で取引先項目名を扱う事にしました。
JavaScriptに var itemStr = '{!Extender.AccountItems}'; と書けばいいことに気づいたのはずっと後になってからでした...気づいた後に修正しました。
選択リストに取引先項目を追加する
document.getElementById() と jQuery('[id$=hogehoge]')
JavaScriptで画面上の要素をIDを使って取得する方法は、document.getElementById()とjQueryのセレクタがあると思います。SVEで開発する際にはdocument.getElementById()は推奨されません。SVEで画面を作った場合には、要素のIDが外側のページブロックセクションIDなどと連結された形で生成されるからです。
これをdocument.getElementById()で取得してしまうと、レイアウトが変わったときにIDが変化してしまって処理が動かなくなってしまう可能性があります。 jQueryのセレクタでjQuery('[id$=hogehoge]')と書くと、「IDの最後がhogehogeになっている全ての要素」を取得してくれます。取りたい要素自身のコンポーネントIDは常に要素のIDの一番最後に書かれるので、レイアウトが変化しても対応できます。
注意すべきなのは、セレクタは「すべての要素」を取ってきてくれるので、取ってきた要素は必ず、Object型の配列に格納される形になります。たとえ欲しい要素が一つだけだったとしても、配列の0番目を参照しないと欲しいデータに触ることが出来ません。document.getElementById()は取得した変数自体が欲しいデータなので、この違いがわからないと私のように何時間も悩む羽目になります!
今回の場合では、取引先項目名の初期表示を10行にしているため、何れにせよセレクタで10行分の要素を取得することになります。 以上を踏まえた上で、最終的な処理が以下のようにできました。
function getAccStr() { var itemStr = '{!Extender.AccountItems}'; var length = itemStr.length; itemStr = itemStr.substr(1 , (length - 2)); var List = itemStr.split(','); var obj = jQuery('[id$=AccItems]'); for(var i = 0 ; i < obj.length ; i++){ for(var j = 1 ; j < List.length ; j++){ obj[i].options[j] = new Option(List[j - 1]); } } } jQuery('document').ready(function() { getAccStr(); });
※今回は全ての取引先項目を取得しましたが、実際には権限によるアクセスコントロールも意識した実装が必要になるかと思いますのでご注意ください。
どうやらメソッドの戻り値がList
データテーブルの初期表示10行の「取引先項目名」をセレクタで取得し、二重ループで取引先項目を詰め込んでいきます。 これで無事に選択リストから取引先項目を選択できるようになりました。
さいごに
項目名を取得して何かに使うという場面がどれくらいあるのか定かではありませんが、個人的には知っておいて損はなさそうだな、という気がしました。 この作業を行っていたのは8月中旬なのですが、そのときはあまり作業内容を記録に残すということをやっていなかったため、この記事を書くのも半分くらいは思い出しながら書いたので骨が折れました。進捗管理の観点からもこまめに作業内容をメモすることとバックアップを取ることの大切さが身にしみてわかりました。
今年最後のTECHBLOGということで、今年自分がどんな作業をしていたのか客観的に振り返る意味も込めてこのような内容を書いてみましたが、いかがでしたでしょうか。最近ではSVEと同じ当社製品であるSkyOnDemandを扱う機会もあり、コーディングやSalesforce標準カスタマイズ以外にも色々なことをやらせて頂いてとてもありがたいです。
まだまだわからないことだらけですが、来年は更に会社の戦力足りうる人材になるべく日々精進して参りたい所存です。
最後に、SkyVisualEditorでの画面作成は本当に簡単にできてとても便利です!2016年12月18日(日)にバージョン6.0がリリースされて様々な機能が追加され、更に便利になりました!ご興味のある方は是非当社にお問い合せください!
それでは皆様、良いお年をお迎えください。