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
信大 仙洞田 5信大 仙洞田 5 

visualforceページの複数配置されたコンポーネントの再描画について

visualforceページに同じコンポーネントを複数設置した際の、visualforceページ側からの再描画について、原因の特定が難しい挙動に遭遇しました。

このvisualforceページでは、visualforceページ(vfp)とコントローラー、visualforceページに配置されるコンポーネント(vfc)と、コンポーネントのコントローラ、MVCにおけるモデルのようなApexクラスの5つの要素を扱っています。
visualforceページには以下のように複数のコンポーネントを置いています。
<c:TestVisualForceComponent input="{!array}" index="0"/>
    <c:TestVisualForceComponent input="{!array}" index="1"/>
    <c:TestVisualForceComponent input="{!array}" index="2"/>
    <c:TestVisualForceComponent input="{!array}" index="3"/>
    <c:TestVisualForceComponent input="{!array}" index="4"/>
この引数に渡すarrayが独自のapexクラスの配列で、VisualForceページのコントローラーで宣言されたものです。
このapexクラスの名前をTDとすると、TDはチェックボックスを管理するためのselectedという名前のBoolean値を持っています。
コンポーネント内では、引数として渡された配列とindexから配列をindexで参照し、その要素のselecetdにゲッターとセッターを定義しています。
以下のようにチェックボックスを設置しています。
<apex:attribute name="input" description="TD. this is imported." type="TD[]" required="true"
    assignTo="{!tds}" />
<apex:attribute name="index" description="index. this is imported." type="Integer" required="true"
    assignTo="{!td_index}" />
...
<apex:form id="form">
<apex:actionFunction name="reRender{!index}" reRender="form" />
<apex:inputCheckbox id="inputcheck" value="{!selected}" selected="false"  onchange="reRender{!index}();"/>
reRender{!index}()としているのは、{!index}を用いて名前を他のコンポーネントと重複しないようにしないと挙動が不安定になるためです。

さて、ここでチェックボックスを全てつけるボタンをvisualforceページで実装しようと考えました。
以下のように、まずvisualforceページのapexコントローラーに関数を定義しました。
public void CheckOrUncheckAll() {
        Boolean exist_check = false;
        for (Integer i = 0; i < COUNT; i++ ){
            if(array[i].selected){
                exist_check = true;
                break;
            }
        }
        for (Integer i = 0; i < COUNT; i++ ){
            array[i].selected = ! exist_check;
        }
    }
次に、visualforceページにボタンを設置しました。
<apex:pageBlock id="block">
      <apex:form>
      ....
        <apex:commandButton action="{!CheckOrUncheckAll}" value="全てにチェックを入れるor外す" reRender="block"/>
ここでボタンをクリックすると実際にarrayの各selectedの値は変更されるのですが、チェックボックスには反映されません。
ところが、あるチェックボックスに対して一度でもチェックを行えば、以降そのチェックしたことがあるチェックボックスのみ、ボタンによって正常にチェック状態が変わるようになります。
(例えば、3,4番目を一度チェックした後にボタンを押すと全てのチェックが消え、もう一度ボタンを押すと3,4番目のチェックだけが入る。しかし、内部的には全てのarrayのselectedがtrueになっている。)

この問題が起こる原因について、どなたかご存知ないでしょうか。
よろしくお願いします。
Taiki YoshikawaTaiki Yoshikawa
変数の値は正しく更新されているとのことですので、reRender処理が適切に実行できていないようです。

共有頂いたコードの範囲で気になった箇所ですが、apex:formタグがページとコンポートの両方で宣言されている部分が原因な気がしました。

formタグはページ側全体にかかるように設置してそれをreRenderの条件指定に使用するといいと思います。

そもそもreRenderが原因かはreRendr処理自体を外すと画面全体が更新されるのでそれで正しく描画されるかで判断できます。
信大 仙洞田 5信大 仙洞田 5
返信が遅くなって申し訳ございません。

コンポーネント側のformを取り除こうにも、actionFunctionはform以下でなければチェッカーに通してもらえないので不可能でした。
reRender自体を外しても同じ結果になりました。

最終的に、dataTableを使ってapexにおける配列の項目を表示しつつ、actionFunctionとparamを駆使して解決いたしました。
同一コンポーネントを同じページで複数扱うことはなるべく控えた方が良いという知見が得られました。

回答ありがとうございました。