+ Start a Discussion
KouheiKouhei 

Visualforceでactionを実行したときのフォーカス遷移について

Visualforceで以下のような現象が起こって困っております。

Spring '12になるまででは起こっていなかったものと認識しております。

何か回避方法など見つけたら教えて頂けないでしょうか。

 

Visualforceで以下のように書いたとします。

 

<apex:page standardController="Test__c" extensions="TestEx">
    <apex:form >
        <apex:inputField value="{!Test__c.Name}"/>
        <apex:inputField id="acc" value="{!Test__c.Account__c}"/>
        <apex:inputField id="cont" value="{!Test__c.Contact__c}"/>
        <apex:commandButton value="test" onclick="TheAction(); return false;"/>
        <apex:actionFunction name="TheAction" action="{!action}" reRender="cont" focus="cont"/>
    </apex:form>
</apex:page>

 

actionの中身は何でも構いません。

とにかくコマンドボタンを押した後に任意のフィールドにカーソルを遷移させたいと考えています。

 

このとき、オブジェクト"Test__c"の項目のいずれかにルックアップ検索条件が設定されている場合、

フォーカスが無条件に一番左上のフィールドに移ってしまいます。

 

上記の例で言えば、Account__cは取引先への参照項目、Contact__cは取引先責任者への参照項目ですが、

Contact__cのルックアップ検索条件に「取引先がAccount__cと一致するものだけ表示」するように設定すると、

Visualforce上でフォーカスが制御出来なくなります。

ルックアップ検索条件を無効にすると問題は起きなくなります。

 

プラットフォームのバグのような気もしますが、何か回避方法がありそうでしたら教えてください。

よろしくお願いします。

Best Answer chosen by Admin (Salesforce Developers) 
minoawminoaw

どうやらこれはinputFieldが持っている処理のようですね。

依存つきルックアップ項目をHTMLとして出力するとき、
条件となるルックアップ項目のテキスト入力をreadonlyにする処理がJavaScriptで行われています。
その処理は当然、再描画後も発動させなければなりません(でないと再描画後にテキスト入力が可能になってしまうので)。

また、項目をreadonlyにした際、ページ内の一番上にある入力要素にフォーカスする関数setFocusが実行されています。
これはおそらく、もしもreadonly化した項目が一番上の項目であった場合、
「画面ロード時に一番上の項目にフォーカスする」という、
Salesforceの入力画面全般に入っている処理が
無効になってしまうことを考えて行っているものではないでしょうか。

この事象は、
「依存元ルックアップのreadonly化」と
「項目をreadonly化した際に一番上の項目にフォーカスする」
の2つの機能が複合して起きた事態であるようです。

対策ですが、これはinputField自体がもつ挙動なので、
あまり綺麗な回避方法はないように思います。
それでもマシな方法は、
今、actionFunctionで指定しているフォーカスを、oncomplete属性で、
JavaScriptで行うことではないでしょうか。

<apex:actionFunction name="TheAction" action="{!action}" reRender="cont" oncomplete="document.getElementById('{!$Component.cont}').focus();"/>

 

 

All Answers

minoawminoaw

どうやらこれはinputFieldが持っている処理のようですね。

依存つきルックアップ項目をHTMLとして出力するとき、
条件となるルックアップ項目のテキスト入力をreadonlyにする処理がJavaScriptで行われています。
その処理は当然、再描画後も発動させなければなりません(でないと再描画後にテキスト入力が可能になってしまうので)。

また、項目をreadonlyにした際、ページ内の一番上にある入力要素にフォーカスする関数setFocusが実行されています。
これはおそらく、もしもreadonly化した項目が一番上の項目であった場合、
「画面ロード時に一番上の項目にフォーカスする」という、
Salesforceの入力画面全般に入っている処理が
無効になってしまうことを考えて行っているものではないでしょうか。

この事象は、
「依存元ルックアップのreadonly化」と
「項目をreadonly化した際に一番上の項目にフォーカスする」
の2つの機能が複合して起きた事態であるようです。

対策ですが、これはinputField自体がもつ挙動なので、
あまり綺麗な回避方法はないように思います。
それでもマシな方法は、
今、actionFunctionで指定しているフォーカスを、oncomplete属性で、
JavaScriptで行うことではないでしょうか。

<apex:actionFunction name="TheAction" action="{!action}" reRender="cont" oncomplete="document.getElementById('{!$Component.cont}').focus();"/>

 

 

This was selected as the best answer
KouheiKouhei

なるほど!よく分かる解説ありがとうございます。

 

ご例示いただいたコードで、手元のサンプルは正しく動くことを確認できました。

これで試してみます。

 

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