やっとVisualforceが完成形になったのでまとめ
これまでも色々なものをVisualforceで作ってきました。昨今ではLWCというものが盛り上がっているのですが、シンプルに印刷用の帳票作るんだったらVisualforceが楽だよなと思っています。
さて、そんなVisualforceの何が完成形なのかについて。
弊社リバネスでは、あらゆるデータをSalesforce上に集めて、それを使ったデータの出力を行うことは日常茶飯事なのですが、その中で実装したいことがいくつかありました。
実装したい条件
1:URLパラメータで情報を出し分けしたい。URL共有するから
2:ページ上のセレクトボックス等を使って条件を変更してrerenderしたい
2−2:条件を変更したらURLも同じ条件で自動的に書き換えたい
1−2:1を行ったときに、2のセレクトボックス等のデータをURLパラメータに入ってる内容にセットしたい
というものでした。
1はVisualforceで処理するなら比較的簡単で、URLパラメータは
ApexPages.CurrentPage().getParameters().get('パラメータ名');
という形式で取得できる。これは簡単。
2の実装について
実装方法は、jsでApexを呼び出してrerenderでページをリフレッシュすること無く内容を書き換えたい。これもそれほど難しいことはなく、慣れれば簡単にできるはず。ただ、著者である私はjsに明るくないので、そもそものパラメータの渡し方とか調べるのが面倒だったんですよね…今回ちゃんと勉強して実装してみました。時間かかってしまった。
Visualforce側からApexへの引数の渡し方は
<apex:actionFunction name="ActionFunction名" action="{!Apexのクラス名}" reRender="書き換えたいID" >
<apex:param name="変数名1" value="変数名1" />
<apex:param name="変数名2" value="変数名2" />
</apex:actionFunction>
こんな形式で、変数を設定し、Apex側で受け取ります。
Apex側では
public String 変数名1{get;set;}
public String 変数名2{get;set;}
という形式で変数を設定しておきましょう。これで受け取るための準備は完了です。
Visualforceに戻ります。
Visualforceで先程のactionFunctionをjsから呼び出す必要があります。
例えば、ドロップダウンリストの選択値が変更された場合にjsを呼ぶとします。
<apex:form id="Apexform名">
<select name="ドロップダウンリストの名前" id="ドロップダウンリストの名前" onchange="js関数名()">
<option value="0">0</option>
<option value="1">1</option>
</select>
</apex:form>
簡単なドロップダウンリストにしました。onchangeで変更を拾って、js関数名()で指定した関数を呼び出します。apex:formの間にはさみます。
onchangeで呼ばれるjsはこんな形です。
<script type="text/javascript">
function js関数名() {
var selectList = document.getElementById('{!$Component.Apexform名}').ドロップダウンリストの名前;
var selectednum = selectList.selectedIndex;
var p_selected = selectList.options[selectednum].value;
ActionFunction名(p_selected,p_selected2); // 先程書いたactionFunctionのパラメータ設定が2つになっていたので便宜上p_selected2を加えていますが、このへんは適宜調整ください。
}
</script>
onchangeでjs関数名が呼ばれて、そこから各種変数をしゅとくしてActionFunctionを呼び出し、引数p_selected,p_selected2を渡しています。
これだけだとURLが切り替わらないので一行追加します。
<script type="text/javascript">
function js関数名() {
var selectList = document.getElementById('{!$Component.Apexform名}').ドロップダウンリストの名前;
var selectednum = selectList.selectedIndex;
var p_selected = selectList.options[selectednum].value;
ActionFunction名(p_selected,p_selected2); // 先程書いたactionFunctionのパラメータ設定が2つになっていたので便宜上p_selected2を加えていますが、このへんは適宜調整ください。
window.history.pushState(null, null, '/apex/VisualforcePage名?p_selected=' + p_selected + '&p_selected2=' + p_selected2);//これでURLが書き換わります
}
</script>
これでURLが書き換わります。Apexが呼ばれてrerenderで内容が書き換わります。HTML自体は、LIST<String>に入れてしまってrepeatで処理する形が楽なのでそうやっちゃってます。
<apex:outputPanel id="actionFunctionのreRenderに書いた書き換えたいID">
<apex:repeat value="{!StringList名}" var="st">
<apex:outputText value="{!st}" escape="false" />
</apex:repeat>
</apex:outputPanel>
これでHTML側(VisualforcePage)からjsでデータをApexの変数に渡してreRenderで書き換える処理が完成しました。
一つの工夫について
このVisualforcePageでは、onchangeで拾ってきたパラメータで表示を書き換える機能と、指定されたURLパラメータを使ってデータを表示する機能があります。それぞれの値を受け取る変数は2つに分けましょう。
例えば日付を格納するような項目があったとしたら
public String p_date{get;set;}
public String s_date{get;set;}
というように、URLパラメータ用と、セレクトボックス等のデータ用の2つに分けて、どちらかが存在したときにその値を使うような形にします。
String datestring;
if(p_date!=NULL){
datestring = p_date;
}else{
datestring = s_date;
}
こうしておけば値が競合しません。
最後に、URLパラメータを含んだ状態で開いた場合に、セレクト等をそのデータで上書きするjsです
window.onload = function() {
//パラメータを取得する
var params = getParameter();
if(params['p_date']!==""){
$("#ドロップダウンリストの名前").val(params['p_date']);
}
}
function getParameter(){
var paramsArray = [];
var url = location.href;
parameters = url.split("#");
if( parameters.length > 1 ) {
url = parameters[0];
}
parameters = url.split("?");
if( parameters.length > 1 ) {
var params = parameters[1].split("&");
for ( i = 0; i < params.length; i++ ) {
var paramItem = params[i].split("=");
paramsArray[paramItem[0]] = paramItem[1];
}
}
return paramsArray;
};
window.onloadで、ページをロードした時のみに発動させます。
URLパラメータをgetParameter関数で取得し、その値を使ってドロップダウンリストのvalueを置き換えます。
ここまでで完成です。やっと理想形になりました。
コードはこちらへ
これにてVisualforce開発を引退してLWC開発に勤しみたいとおもいます。
noteにはこれまでの経験を綴っていこうかと思います。サポートによって思い出すモチベーションが上がるかもしれない。いや、上がるはずです。