Visualforceページのプルダウンリストでパラメータを変更する:2つ連動の場合
Visualforceページを使ってダッシュボードを作ることがままあるのですが、URLパラメータを付与して表示を変えたりすることがあると思います。
その場合はVisualvoceページ側にjavascriptを記述してゴニョゴニョする必要があったりして、js初学者にはツラい。
やっとこAPEXに慣れてきたのに今度はフロントエンドかよ…となった人は使ってみてください。
今回実現するのはこんな感じのプルダウンメニューです。
左側の名前をセレクトすると、それに紐付いた右側のプルダウンメニューが変化します。Goボタンを押すと、該当データを表示するためのパラメータが付与されたURLへと飛んでいきます。
連動プルダウンの仕組み
仕組みは色々と調べてみた結果、一番簡単なのは全てのプルダウンメニューをレンダリングしてしまって、jsで表示を切り替えるというものでした。
最初にapex側で2つのリスト(それ以上の場合でも基本的には同じでしょう)を表示してしまいましょう。それが以下のコードです。
Visualforceページ
リストレンダリング部分
[code]
<form name="userindex">
<div class="pulldownset">
<select name="userName" class="slds-select mainselect" style="width:8em;">
<apex:repeat value="{!UserNameList}" var="unl">
<option value="{!unl.Id}">{!unl.Name}</option>
</apex:repeat>
</select>
<apex:outputText value="{!subList}" escape="false" />
<input type="button" value="GO" onclick="jump();" />
</div>
</form>
[/code]
js部分
jsでuserNameで選択されたvalueを元にsubリストのvalueと照合して表示非表示を切り替える
jumb()はプルダウンメニューで選択されているvalueを元に該当URLへと遷移するためのシンプルなボタンです。
[code]
<script type="text/javascript">
// ▼HTMLの読み込み直後に実行:
var targetSub;
var targetSubtext;
document.addEventListener('DOMContentLoaded', function() {
// ▼全てのプルダウンメニューセットごとに処理
var mainBoxes = document.getElementsByClassName('pulldownset');
for( var i=0 ; i<mainBoxes.length ; i++) {
var mainSelect = mainBoxes[i].getElementsByClassName("mainselect"); // 1階層目(メイン)のプルダウンメニュー(※後でvalue属性値を参照するので、select要素である必要があります。)
targetSub = document.getElementById( mainSelect[0].value ); // 「1階層目のプルダウンメニューで選択されている項目のvalue属性値」と同じ文字列をid属性値に持つ要素を得る
targetSub.style.display = 'inline';
mainSelect[0].onchange = function () {
// ▼同じ親要素に含まれているすべての2階層目(サブ)要素を消す
var subBox = this.parentNode.getElementsByClassName("subbox"); // 同じ親要素に含まれる.subbox(※select要素に限らず、どんな要素でも構いません。)
for( var j=0 ; j<subBox.length ; j++) {
subBox[j].style.display = 'none';
}
// ▼指定された2階層目(サブ)要素だけを表示する
if( this.value ) {
targetSub = document.getElementById( this.value ); // 「1階層目のプルダウンメニューで選択されている項目のvalue属性値」と同じ文字列をid属性値に持つ要素を得る
targetSub.style.display = 'inline';
}
}
}
});
function jump(){
location.href = '/apex/Visualforceページ名?userID=' + userindex.userName.value + '&id=' + targetSub.value + '&subkey=' + targetSub.options[targetSub.selectedIndex].text;
}
//選択されたパラメータをページ表示タイミングで選択された状態にしたい
//変数argはオブジェクトですよ
var arg = new Object;
// 変数pairにURLの?の後ろを&で区切ったものを配列にして代入
var pair = location.search.substring(1).split('&');
// location.search.substring(1)は、URLから最初の1文字 (?記号) を除いた文字列を取得する
// .split('&')は&で区切り配列に分割する
// for文でrairがある限りループさせる
for(var i=0;pair[i];i++) {
// 変数kvにpairを=で区切り配列に分割する
var kv = pair[i].split('=');// kvはkey-value
// 最初に定義したオブジェクトargに連想配列として格納
arg[kv[0]]=kv[1]; // kv[0]がkey,kv[1]がvalue
}
//SELECTに設定
if(arg.userName != ''){
document.form.userName.value=arg.userName;
}
if(arg.period != ''){
document.targetSub.value=targetSub.value;
}
</script>
[/code]
実際に表示されるHTML
*js部分はそのまま表示されるので割愛
[code]
<form name="userindex">
<div class="pulldownset">
<select class="slds-select mainselect" name="userName" style="width:8em;">
<option value="00************AAA">名前A</option> <!-- valueの値はSalesforceのユーザーIDです -->
<option value="00************AAB">名前B</option> <!-- valueの値はSalesforceのユーザーIDです -->
<option value="00************AAC">名前C</option> <!-- valueの値はSalesforceのユーザーIDです -->
</select>
<select name="period" id="00************AAA" class="subbox">
<option value="必要なパラメータ">2017-08</option> <!-- valueの値は何かしら必要なパラメータ -->
<option value="必要なパラメータ">2017-07</option> <!-- valueの値は何かしら必要なパラメータ -->
<option value="必要なパラメータ">2017-06</option> <!-- valueの値は何かしら必要なパラメータ -->
<option value="必要なパラメータ">2017-05</option> <!-- valueの値は何かしら必要なパラメータ -->
</select>
<select name="period" id="00************AAB" class="subbox">
<option value="必要なパラメータ">2017-08</option> <!-- valueの値は何かしら必要なパラメータ -->
<option value="必要なパラメータ">2017-07</option> <!-- valueの値は何かしら必要なパラメータ -->
</select>
<select name="period" id="00************AAC" class="subbox">
<option value="必要なパラメータ">2017-08</option> <!-- valueの値は何かしら必要なパラメータ -->
</select>
<input onclick="jump();" type="button" value="GO" />
</div>
</form>
[/code]
Apex
[code]
public class yourClass {
public LIST<User> UserNameList{get;set;}
public yourClass(ApexPages.StandardController controller) {
UserNameList = new LIST<User>();
getUserNameList(UserNameList);
getSubList(UserNameList); // サブリスト用のデータ取得用のクラスを適当に作る
}
public List<User> getUserNameList(LIST<User> UserNameList) {
UserNameList = [SELECT Id,Name From User WHERE IsActive = true];
return UserNameList;
}
}
[/code]