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
yuyu 

commandButton実行時にaction属性で指定した関数が実行されません

お世話になっております。

Visualforceページにページ遷移しない関数をaction属性に指定したcommandButtonを作成したのですが、

このボタンを連続で実行した時、actionで指定した関数が実行されずに表示中のページが再読み込みされる時があります。

この時コントローラのクラス変数やビューステートが初期化されるため、commandButtonを実行する前と画面の整合性が取れなくなっています。

 

自分で確認した限りではaction関数実行後の画面が再描画中(画面下部のCopyright が表示されていない時)に、再度action関数が実行されると上記の症状が発生していました。

症状を発生させない、又は画面の再描画中はボタンを無効化する方法はあるのでしょうか?

 

症状を確認する為のVisualforceページのサンプルを作成しました。

下記の画面で以下の操作を行うと症状が発生します。

 ①「テスト1」ボタンをクリックする。(「テスト2」ボタンが表示されます。)

 ②「テスト2」ボタンをクリックする。(画面が再描画されますが表示は変わりません)

 ③「テスト2」ボタンを連続でクリックして、画面の再描画中にボタンをクリックする。

   (クラス変数とビューステートが初期化されるため、「テスト2」ボタンが画面から消えます。)

 

 【Visualforceページ】

<apex:page controller="TestClass">
<apex:form id="form">
    <apex:commandButton value="テスト1" action="{!test1}"/>
    <apex:commandButton value="テスト2" action="{!test2}" rendered="{!mode == '1'}"/>   
</apex:form>
</apex:page>

 

【コントローラクラス】

public class TestClass {

  public String mode { get; set; }
  public List<ResultClass> resultList { get; set; }
  
  public TestClass() {
    mode = Apexpages.currentPage().getParameters().get('mode');
    
    //ビューステート負荷データ作成
    resultList = new List<ResultClass>();     
    if(mode == '1'){
        for (Integer i = 2; i < 1000; i++) {
            ResultClass result = new ResultClass();
            result.id = 'id-' + i;
            result.value1 = 'value1-' + i;
            result.value2 = 'value2-' + i;
            result.value3 = 'value3-' + i;
            result.value4 = 'value4-' + i;
            result.value5 = 'value5-' + i;
            result.value6 = 'value6-' + i;
            result.value7 = 'value7-' + i;
            result.value8 = 'value8-' + i;
            result.value9 = 'value9-' + i;
            result.value10 = 'value10-' + i;
            resultList.add(result);
        }
    }
  }

  public PageReference test1() {
        PageReference newPage = Page.testPage;
        newPage.getParameters().put('mode', '1');
        newPage.setRedirect(true);
        return newPage;
  }
  
  public PageReference test2() {
    return null;
  }
  
    public class ResultClass {
        public String id { get; set; }
        public String value1 { get; set; }
        public String value2 { get; set; }
        public String value3 { get; set; }
        public String value4 { get; set; }
        public String value5 { get; set; }
        public String value6 { get; set; }
        public String value7 { get; set; }
        public String value8 { get; set; }
        public String value9 { get; set; }
        public String value10 { get; set; }
    }  

}

 

Taiki YoshikawaTaiki Yoshikawa

commanButtonのstatusという属性でactionの開始から終了までの情報を取得することができます。

あくまでサンプルですがこんな感じのことが可能です。

 

Component

<apex:component id="LoadingComponent" >
	<apex:actionStatus id="Loading">
	    <apex:facet name="start">
	        <apex:outputpanel style="position:absolute;height:100%;width:100%;">
                <apex:outputpanel style="position:fixed;top:50%;left:50%;">
                    <apex:image url="/img/loading.gif" />
                    &nbsp;
                    <apex:outputText value="Loading..." style="color:#696969;font-weight:bold;font-size:16px;" />
                </apex:outputpanel>                    
	        </apex:outputpanel>                                                                     
	    </apex:facet>
	</apex:actionStatus>
</apex:component>

 Page

<apex:page controller="TestClass">
<apex:form id="form">
    <c:loadingSample />
    <apex:commandButton value="テスト1" action="{!test1}" reRender="form" status="Loading" />
    <apex:commandButton value="テスト2" action="{!test2}" rendered="{!mode == '1'}" reRender="form" status="Loading"/>   
</apex:form>
</apex:page>

 こんな感じで処理中のクリックを防ぐことができると思います。

yu1513yu1513

 

status属性を利用する事で2重起動を防ぐ事が出来ました。

onclick属性を利用したjavascriptの 二度押し防止処理を行っていましたが、

actionの終了を取得できないため正常に動作してくれませんでした。

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

Taiki YoshikawaTaiki Yoshikawa

status属性を利用する事で2重起動を防ぐ事が出来たとのことでよかったです。

もしcommandButtonからJavaScriptを呼び出しでactionFunctionでApexクラスを呼び出す場合はこんな感じで対応が可能です。

 

<apex:actionFunction name="sample" action="{!sample}" reRender="form" status="Loading"/>

 このときcommandButton側でreRenderやstatusの指定は必要ありません。