function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
ruparuparuparupa 

選択リスト (複数選択)項目のonchangeイベントで変更した値を取得したい

いつもお世話になっております。

apex:inputFieldタグで出力した「選択リスト (複数選択)」型の項目のonchangeイベントで
変更した値を取得したいのですが、どのように実装すればよいでしょうか。

テキスト項目ですと、onchangeイベントで変更した値を取得できるのですが、
選択リスト (複数選択)項目ではどのようにしたら良いのかわかりませんでした。

【再現手順】
1.取引先に、選択リスト (複数選択)項目「MultiPicklistField」を作成する
2.下記ページを作成する
<apex:page standardController="Account" showHeader="true" sidebar="false" recordSetVar="Accounts" id="page">
<apex:form>
  <apex:pageBlock mode="edit" id="block">
    <apex:pageBlockSection title="ApexTable" columns="1">
      <apex:pageBlockTable value="{!Accounts}" var="item">
        <apex:column headerValue="{!$ObjectType.Account.Fields.Name.Label}">
          <apex:inputField value="{!item.Name}" onchange="alert(event.target.value);"/>
        </apex:column>
        <apex:column headerValue="{!$ObjectType.Account.Fields.MultiPicklistField__c.Label}">
          <apex:inputField value="{!item.MultiPicklistField__c}" onchange="alert(event.target.value);"/>
        </apex:column>
      </apex:pageBlockTable>
    </apex:pageBlockSection>
  </apex:pageBlock>
</apex:form>
</apex:page>
3.ページにて動作確認
①テキスト項目(取引先名)を変更し、テキスト項目以外の箇所をクリックする
 →変更した値がアラートされる
②複数選択リストの項目(MultiPicklistField)を変更する
 →何も起こらない(★ここでテキスト項目と同様に、変更した値を取得したい★)

どうぞ宜しくお願い致します。
Best Answer chosen by ruparupa
Taiki YoshikawaTaiki Yoshikawa
『document.getElementById('{!$Component.pickFields}').value』という感じに取れないかなと試してみたところ、値自体は取得できたのですが、選択済みリストの一番上にある値だけが表示されるという結果となりました。

方法があるか調べてみたところ、『document.getElementById('{!$Component.pickFields}').options』というように指定する必要があるみたいです。これで複数選択リストの値リストを取得できました。

取得した値リストをループで回しながら、『selected』で選択済みの値かを判定できます。
<apex:page standardController="Account" showHeader="true" sidebar="false" id="page">
  <apex:form>
    <apex:pageBlock mode="edit" id="block">
      <apex:pageBlockSection title="ApexTable" columns="1">
        <apex:inputField value="{!Account.MultiPicklistField__c}" onchange="return changePick();" id="pickFields"/>
        <script>
          function changePick() {
            var options = document.getElementById('{!$Component.pickFields}').options;
		    for(var i = 0; i < options.length; i++){
		      console.log(options[i].value + ' : ' + options[i].selected);
            }; 
            return false;
          }
        </script>
      </apex:pageBlockSection>
    </apex:pageBlock>
  </apex:form>
</apex:page>


1つずつ選択済みかを判定する必要がありそうですが、ひとまずこんな感じで処理できそうでした。
User-added image

All Answers

Taiki YoshikawaTaiki Yoshikawa
『document.getElementById('{!$Component.pickFields}').value』という感じに取れないかなと試してみたところ、値自体は取得できたのですが、選択済みリストの一番上にある値だけが表示されるという結果となりました。

方法があるか調べてみたところ、『document.getElementById('{!$Component.pickFields}').options』というように指定する必要があるみたいです。これで複数選択リストの値リストを取得できました。

取得した値リストをループで回しながら、『selected』で選択済みの値かを判定できます。
<apex:page standardController="Account" showHeader="true" sidebar="false" id="page">
  <apex:form>
    <apex:pageBlock mode="edit" id="block">
      <apex:pageBlockSection title="ApexTable" columns="1">
        <apex:inputField value="{!Account.MultiPicklistField__c}" onchange="return changePick();" id="pickFields"/>
        <script>
          function changePick() {
            var options = document.getElementById('{!$Component.pickFields}').options;
		    for(var i = 0; i < options.length; i++){
		      console.log(options[i].value + ' : ' + options[i].selected);
            }; 
            return false;
          }
        </script>
      </apex:pageBlockSection>
    </apex:pageBlock>
  </apex:form>
</apex:page>


1つずつ選択済みかを判定する必要がありそうですが、ひとまずこんな感じで処理できそうでした。
User-added image
This was selected as the best answer
Taiki YoshikawaTaiki Yoshikawa
上記のJS側の処理はサンプルです。inputFieldのIDをパラメータとして渡すなどすることで、pageBlockTable内の複数の選択リスト項目にも対応できると思います。
Taiki YoshikawaTaiki Yoshikawa
項目IDはonchangeイベントでパラメータとして渡すようにすることで、複数データが存在する場合にも対応できます。こんな感じの書き方でどうでしょうか。
<apex:page standardController="Account" showHeader="true" sidebar="false" recordSetVar="Accounts" id="page">
  <apex:form id="form">
    <apex:pageBlock mode="edit" id="block">
      <apex:pageBlockSection title="ApexTable" columns="1" id="section">
        <apex:pageBlockTable value="{!Accounts}" var="item" id="blockTable">
          <apex:column headerValue="{!$ObjectType.Account.Fields.Name.Label}">
            <apex:inputField value="{!item.Name}" onchange="alert(event.target.value);"/>
          </apex:column>
          <apex:column headerValue="{!$ObjectType.Account.Fields.MultiPicklistField__c.Label}">
            <apex:inputField value="{!item.MultiPicklistField__c}" onchange="changePick('{!$Component.pickId}');" id="pickId"/>
          </apex:column>
        </apex:pageBlockTable>
      </apex:pageBlockSection>
    </apex:pageBlock>
  </apex:form>
  <script>
    function changePick(prmId) {
      console.log('★ID = ' + prmId);
      var options = document.getElementById(prmId).options;
      for(var i = 0; i < options.length; i++){
        console.log(options[i].value + ' : ' + options[i].selected);
      }; 
      return false;
    }
  </script>
</apex:page>
User-added image
 
Taiki YoshikawaTaiki Yoshikawa
onchangeのところとJSのところです
<apex:inputField value="{!item.MultiPicklistField__c}" onchange="changePick('{!$Component.pickId}');" id="pickId"/>
<script>
    function changePick(prmId) {
      console.log('★ID = ' + prmId);
      var options = document.getElementById(prmId).options;
      for(var i = 0; i < options.length; i++){
        console.log(options[i].value + ' : ' + options[i].selected);
      }; 
      return false;
    }
  </script>


 
ruparuparuparupa
Taiki Yoshikawaさん

何度もご丁寧に誠にありがとうございます。
非常にわかりやすく、お力添えに感謝しております。

厚かましいのですが、もう1点伺っても宜しいでしょうか。

onchangeのときに選択ボックスの値を設定できるか試すために、
ご教授頂いたソースに「options[i].selected=true;」という1文を追加してみました。
<script>
    function changePick(prmId) {
      console.log('★ID = ' + prmId);
      var options = document.getElementById(prmId).options;
      for(var i = 0; i < options.length; i++){
        console.log(options[i].value + ' : ' + options[i].selected);
        options[i].selected=true;
      }; 
      return false;
    }
  </script>
私の予想では、選択肢一つを選択済みにすれば一緒に全部選択済みになるのではないかと思ったのですが、
そうなりませんでした。
しかし、続けてもう一度一つの値を選択済みにしてみると、全部選択済みになりました。

選択ボックスの値を設定する方法をご教授頂けないでしょうか。
上記ソースでは何故うまく動かないのでしょうか。

重ね重ねで恐縮ですが、どうぞ宜しくお願い致します。
ruparuparuparupa
また、一つの選択リストを変更したら他の選択リストも連動して同じ動きをさせる
というようなことはできるでしょうか?
Taiki YoshikawaTaiki Yoshikawa
inputFieldをつかった複数選択リストは表示の際に裏側でいろいろ対応してくれているので、JSでちょっと値をセットするだけだと描画に反映されないのかもしれませんね。

actionSupportをつかってApexクラス側で値を変更するなどの処理を行い、reRenderで再描画する方がシンプルに対応できるかもしれません。
ruparuparuparupa
JSで無理やり実装できたのですが、あやしいですね。。
何度も誠にありがとうございました。