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
k_ogawak_ogawa 

チェックボックス一括選択

お世話になっております。
またまた質問させて頂きます。

VisualForceとapexを使って、チェックボックスで選ばれたデータを登録する。という
プログラムを作成しております。

そこで、チェックボックスの一括選択の処理を追加しようと思ったのですが、なかなかうまくいきません。

以下プログラムです。

<Apex>
public Boolean CheckChange {get; set;}
integer counter = 0;
// イベントオブジェクト内の選択リストをチェックボックスで表示
public List<SelectOption> getSelOptions() {
        List<SelectOption> seloptions = new list<SelectOption>();
        Schema.DescribeFieldResult fieldResult = Event__c.brand__c.getDescribe();
        List<Schema.PicklistEntry> pickListEntry = fieldResult.getPicklistValues();
        for (Schema.PicklistEntry pick: pickListEntry) {
            seloptions.add(new selectOption(pick.getValue(), pick.getLabel()));
            counter = counter +1;
        }
        return seloptions;
}

/** チェックボックス全選択処理 */
    public void ToggleChange(){
   // 選択リストの数分チェックボックスにCheckChangeの結果を反映する
        for(Integer i = 0; i < counter; i++){
//            seloptions.add(new selectOption(CheckChange));   ←ここの処理がわかりません。
        }
    }

<Visualforce>
<apex:pageBlockSection title="ブランド選択">

          <apex:inputCheckbox value="{!CheckChange}">
               <apex:actionSupport action="{!ToggleChange}" event="onchange" rerender="theForm"/>
          </apex:inputCheckbox>

          <apex:selectCheckboxes value="{!selections}" layout="pageDirection">
              <apex:selectOptions value="{!seloptions}"/>
          </apex:selectCheckboxes>
   </apex:pageBlockSection>



このように記述しているのですが、一括でチェックのON/OFFをすることが出来ません。
間違っているところやアドバイスなどありましたらよろしくお願い致します。
Best Answer chosen by k_ogawa
Taiki YoshikawaTaiki Yoshikawa
Apexの処理で一括チェックを付けたい場合は上の方法で対応可能ですが、一括チェックの処理をApex内で行うと少しモッサリした感じが気になってしまいます。複雑な処理はApexでやった方がいいと思いますが、一括チェックのようなシンプルな処理の場合はJavaScriptで対応してしまった方がいいと思います。

Google Chromeの場合、右クリック→要素を選択でその要素のIDを確認することができます。

User-added image

apex:selectCheckboxesのチェックボックスが3つある場合次のようにIDが連番になっていることが確認できます。
  • page:form:checkBoxes:0
  • page:form:checkBoxes:1
  • page:form:checkBoxes:2

次のような感じでJavaScriptを使って一括チェックを実行できます。
// リスト件数分チェック処理を実行
for (var i = 0; i < itemCnt; i++) {
    document.getElementById(checkId + ':' + i).checked = true;
}



ApexとJavaScriptの一括チェック処理のサンプルです。このままコピペして動作確認できると思います。ApexとJavaScriptで結構違いがでるので確認してみてください。

selectCheckboxes.page
<apex:page controller="selectCheckboxesCon" id="page">
    <apex:form id="form">
        <apex:selectCheckboxes value="{!countries}" id="checkBoxes">
            <apex:selectOptions value="{!items}"/>
        </apex:selectCheckboxes><br/>
        <apex:commandButton value="Apex Check!!" action="{!doApexCheck}" reRender="form" />
        <apex:commandButton value="JavaScript Check!!" onclick="return allChecked();" />
    </apex:form>
    <script type="text/javascript">
        function allChecked() {
            
            // apex:selectOptionsの件数を取得
            var itemCnt = '{!items.size}';
            console.log(itemCnt);
            
            // apex:selectCheckboxesのidを取得
            var checkId = '{!$Component.form.checkBoxes}';
            console.log(checkId);
            
            // リスト件数分チェック処理を実行
            for (var i = 0; i < itemCnt; i++) {
                    document.getElementById(checkId + ':' + i).checked = true;
            }
            
            return false;    
        }
    </script>
</apex:page>

selectCheckboxesCon.cls
public with sharing class selectCheckboxesCon {

    public List<String> countries {get; set;}
    public List<SelectOption> items {get; set;}
    
    public selectCheckboxesCon() {
        this.items = getItems();
        this.countries = new List<String>();
    }

    public List<SelectOption> getItems() {
        List<SelectOption> options = new List<SelectOption>();
        options.add(new SelectOption('US','US'));
        options.add(new SelectOption('CANADA','Canada'));
        options.add(new SelectOption('MEXICO','Mexico'));

        return options;
    }
    
    /**
     * ボタンクリック時にチェック
     */
    public void doApexCheck() {
        System.debug('Check = ' + this.countries);
        
        // selectCheckBoxsの値をセット
        this.countries = new List<String>();
        for (SelectOption o : this.items) {
            this.countries.add(o.getValue());
        }
        
        // selectCheckBoxsの値をクリア
        //this.countries = new List<String>;
    }
}


All Answers

Taiki YoshikawaTaiki Yoshikawa
apex:selectCheckboxesの値の持ち方ですが、チェックボックス毎にTrue/Falseを持っているのではなく、次のようにカンマ区切りの文字列として保持されます。

User-added image
例えば次のようなリスト値を持っているとすると...
public List<SelectOption> getItems() {
    List<SelectOption> options = new List<SelectOption>();
    options.add(new SelectOption('US','US'));
    options.add(new SelectOption('CANADA','Canada'));
    options.add(new SelectOption('MEXICO','Mexico'));

    return options;
}
次の処理でチェックをつけた状態にすることができます。
// selectCheckBoxsの値をセット
this.countries = new List<String>();
this.countries.add('US');
this.countries.add('CANADA');
this.countries.add('MEXICO');

List<SelectOption>の件数分セットすればいいのでこんな感じになります。
// selectCheckBoxsの値をセット
this.countries = new List<String>();
for (SelectOption o : this.items) {
    this.countries.add(o.getValue());
}


チェックを一括解除したい場合は次のように「new List<String>()」で対応可能です。
// selectCheckBoxsの値をクリア
this.countries = new List<String>();

Apexクラスの処理でapex:selectCheckboxesの一括チェックはこんな感じで対応できると思います。


Taiki YoshikawaTaiki Yoshikawa
Apexの処理で一括チェックを付けたい場合は上の方法で対応可能ですが、一括チェックの処理をApex内で行うと少しモッサリした感じが気になってしまいます。複雑な処理はApexでやった方がいいと思いますが、一括チェックのようなシンプルな処理の場合はJavaScriptで対応してしまった方がいいと思います。

Google Chromeの場合、右クリック→要素を選択でその要素のIDを確認することができます。

User-added image

apex:selectCheckboxesのチェックボックスが3つある場合次のようにIDが連番になっていることが確認できます。
  • page:form:checkBoxes:0
  • page:form:checkBoxes:1
  • page:form:checkBoxes:2

次のような感じでJavaScriptを使って一括チェックを実行できます。
// リスト件数分チェック処理を実行
for (var i = 0; i < itemCnt; i++) {
    document.getElementById(checkId + ':' + i).checked = true;
}



ApexとJavaScriptの一括チェック処理のサンプルです。このままコピペして動作確認できると思います。ApexとJavaScriptで結構違いがでるので確認してみてください。

selectCheckboxes.page
<apex:page controller="selectCheckboxesCon" id="page">
    <apex:form id="form">
        <apex:selectCheckboxes value="{!countries}" id="checkBoxes">
            <apex:selectOptions value="{!items}"/>
        </apex:selectCheckboxes><br/>
        <apex:commandButton value="Apex Check!!" action="{!doApexCheck}" reRender="form" />
        <apex:commandButton value="JavaScript Check!!" onclick="return allChecked();" />
    </apex:form>
    <script type="text/javascript">
        function allChecked() {
            
            // apex:selectOptionsの件数を取得
            var itemCnt = '{!items.size}';
            console.log(itemCnt);
            
            // apex:selectCheckboxesのidを取得
            var checkId = '{!$Component.form.checkBoxes}';
            console.log(checkId);
            
            // リスト件数分チェック処理を実行
            for (var i = 0; i < itemCnt; i++) {
                    document.getElementById(checkId + ':' + i).checked = true;
            }
            
            return false;    
        }
    </script>
</apex:page>

selectCheckboxesCon.cls
public with sharing class selectCheckboxesCon {

    public List<String> countries {get; set;}
    public List<SelectOption> items {get; set;}
    
    public selectCheckboxesCon() {
        this.items = getItems();
        this.countries = new List<String>();
    }

    public List<SelectOption> getItems() {
        List<SelectOption> options = new List<SelectOption>();
        options.add(new SelectOption('US','US'));
        options.add(new SelectOption('CANADA','Canada'));
        options.add(new SelectOption('MEXICO','Mexico'));

        return options;
    }
    
    /**
     * ボタンクリック時にチェック
     */
    public void doApexCheck() {
        System.debug('Check = ' + this.countries);
        
        // selectCheckBoxsの値をセット
        this.countries = new List<String>();
        for (SelectOption o : this.items) {
            this.countries.add(o.getValue());
        }
        
        // selectCheckBoxsの値をクリア
        //this.countries = new List<String>;
    }
}


This was selected as the best answer
k_ogawak_ogawa
Taiki 様
お世話になっております。

そうなんですね!True/Falseで判断できるものだと思っていました。

頂いたサンプルで早速試してみたのですが、JavaScriptのほうが作動してくれず、結果を見ることが出来ませんでした。

ちなみに、サンプルだとボタンを追加して選択していますが、チェックボックスでの制御は難しいでしょうか?

Taiki YoshikawaTaiki Yoshikawa
JavaScriptエラーですか。もしかするとブラウザの問題かもしれません。
console.logの部分がエラーになるブラウザがあった気がします。

Google Chromeで検証しているのでChromeで試してみてもらえるといいかもしれないです。
もしくはconsole.logの処理を除外してみてください。


チェックボックスの制御でも対応可能です。
Apexで処理する場合はapex:actionSupportでApexクラスの処理を呼び出す形になると思います。
jsの方はonclickかonchangeイベントで処理を行えます。

apex:actionSupport - Salesforce.com
https://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_actionSupport.htm
k_ogawak_ogawa
console.logの部分を外してみたところうまく動きました。

ただ、元々私が作成しているほうにこの処理を移植しようと思うとなかなかうまくいきません。
というかどのように反映させればよいかがよくわかりません。

もしよろしければ、上記のソースに当てはめて頂けないでしょうか?

また、javascriptの
for (var i = 0; i < itemCnt; i++) {
      document.getElementById(checkId + ':' + i).checked = true;
}
この部分についてなのですが、直接trueを代入しているかと思いますが、制御基になるチェックボックスが、trueになれば選択、falseになれば解除
といったようなことは可能でしょうか?

厚かましいお願いとは重々承知しておりますが、よろしくお願いいたします。
Taiki YoshikawaTaiki Yoshikawa
書き方はいろいろあると思いますが、これでチェックボックスにチェックしたタイミングで一括チェックのON / OFFができると思います。

<apex:page controller="selectCheckboxesCon" id="page">
    <apex:form id="form">
        
        <!-- 一括チェック用のチェックボックス -->
        <apex:inputCheckbox value="{!CheckChange}" onchange="return allChecked();" id="checkChange" />
        
        <apex:selectCheckboxes value="{!countries}" id="checkBoxes">
            <apex:selectOptions value="{!items}"/>
        </apex:selectCheckboxes><br/>
    </apex:form>
    <script type="text/javascript">
        function allChecked() {
            
            // 一括チェックボックスのID取得
            var targetCheckId = '{!$Component.form.checkChange}';
            var targetCheck = document.getElementById(targetCheckId);
            
            var itemCnt = '{!items.size}';
            var checkId = '{!$Component.form.checkBoxes}';
            
            for (var i = 0; i < itemCnt; i++) {
                // 一括チェックボックスと同じ値をセット
                document.getElementById(checkId + ':' + i).checked = targetCheck.checked;
            }
            
            return false;    
        }
    </script>
</apex:page>

k_ogawak_ogawa
ありがとうございます。
やっと意味が解りました!

チェックリストの並びを縦並びにしたいがために、
ずっと<apex:selectCheckboxes>にしていたためJavaScriotが動かなかったようです。

そこで疑問がわいたのですが、
<apex:selectCheckboxes>と<apex:inputCheckbox>の違いとは何なのでしょうか?
また、<apex:inputCheckbox>を使ったときにチェックボックスを縦並びにする方法はありますでしょうか?

重ね重ね申し訳ございませんが、よろしくお願い致します。
Taiki YoshikawaTaiki Yoshikawa
<apex:selectCheckboxes>と<apex:inputCheckbox>の違いは関連する複数のチェックボックス表示と単体とチェックボックス表示という感じだと思います。

<apex:selectCheckboxes>はリストに値をセットするだけで動的に作成することができ、上のサンプルのようにJavaScriptで処理する際にリスト番号を変えるだけで値をセットすることができます。

<apex:inputCheckbox>は変数固定で使用するので動的に追加したりするのには向いていません。IDもそれぞれ関連しないものが割り当てられるのでJavaScript内で一括チェックするには向いていないのかなと思います。

表示するチェックボックスが固定の場合は、<apex:inputCheckbox>で問題ないと思います。こちらで縦並びにしたい場合はCSSやTeble表示などで対応できると思います。今回のような場合は一括チェック用のチェックボックスを<apex:inputCheckbox>で表示して、関連するチェックボックスは<apex:selectCheckboxes>で表示するイメージなのかなと思っています。
k_ogawak_ogawa
Taiki 様

詳しいご説明ありがとうございます。
まだ少し理解できない部分もあるのですが、自分なりに理解を深めてゆきたいと思います。

毎回アドバイスをいただけてうれしい限りです。
ありがとうございました。