フォームの項目のタブ順序の設定
Visualforce フォームには入力項目をタブで移動する場合の「自然な順序」(左から右および上から下) が用意されています。一部のフォームでは、この順序が必ずしも最も効率が良い配置方法、あるいはアクセスしやい配置方法ではない場合があります。ページの入力コンポーネントおよびその他のコンポーネントに tabIndex 属性を設定してこのタブ順序を任意の順序に変更できます。次に例を示します。
1swfobject.registerObject("clippy.codeblock-0", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<apex:page standardController="Account">
18 <apex:form>
19 <apex:pageBlock title="Edit Account: {!Account.Name}">
20 <apex:pageBlockSection title="Account Details" columns="1">
21 <apex:inputField value="{!Account.Name}" tabIndex="4"/>
22 <apex:inputField value="{!Account.Website}" tabIndex="3"/>
23 <apex:inputField value="{!Account.Industry}" tabIndex="2"/>
24 <apex:inputField value="{!Account.AnnualRevenue}" tabIndex="1"/>
25 </apex:pageBlockSection>
26 </apex:pageBlock>
27 </apex:form>
28</apex:page>
29このページを表示して Tab キーを押すと、通常期待する順序とは逆順に有効な項目が変わります。
tabIndex 属性は 0 ~ 32767 の整数、または評価結果がこの範囲の整数値になる式である必要があります。タブ順序は、ユーザが Tab キーを押すと選択される最初のコンポーネントであるコンポーネント 0 から始まります。
tabIndex 属性は次の Visualforce コンポーネントで設定できます。
- <apex:commandButton>
- <apex:commandLink>
- <apex:inputCheckbox>
- <apex:inputField>
- <apex:inputFile>
- <apex:inputSecret>
- <apex:inputText>
- <apex:inputTextarea>
- <apex:outputLabel>
- <apex:outputLink>
- <apex:selectCheckboxes>
- <apex:selectList>
- <apex:selectRadio>
反復内のコンポーネントに対する tabIndex の設定
<apex:dataTable> または <apex:repeat> の内部などで反復コンポーネントによって繰り返し処理されるコンポーネントに tabIndex 属性を設定できます。ただし、この場合、必要な作業が若干増えます。
アクセスされると自動的に増分を行う Apex の getter メソッドを使用して tabIndex を設定するというソリューションは、明解に見えますが、機能しません。Visualforce は getter メソッドの結果をキャッシュするため、ページを使用するたびに getter メソッドがコールされるとは限りません。Visualforce の getter メソッドの実装方法についての詳細は、「Visualforce ページ内の実行順序」を参照してください。
代わりに、反復処理されるコレクションの各要素でオブジェクト参照または項目参照と共に tabIndex 値を指定できます。次に、Visualforce ページ内にこれがどのように表示されるかを示します。
1swfobject.registerObject("clippy.codeblock-2", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<apex:page controller="OppsController">
18 <apex:form>
19 <apex:dataTable value="{!OpportunitiesWithIndex}" var="oppWrapped">
20 <apex:column>
21 <apex:facet name="header">Opportunity</apex:facet>
22 <apex:outputField value="{!oppWrapped.opp.name}"/>
23 </apex:column>
24 <apex:column>
25 <apex:facet name="header">Amount</apex:facet>
26 <apex:inputField value="{!oppWrapped.opp.amount}"
27 tabindex="{!oppWrapped.tabIndex}"/>
28 </apex:column>
29 </apex:dataTable>
30 </apex:form>
31</apex:page><apex:dataTable> コンポーネントは商談レコードのリストを反復処理しません。ただし、{!oppWrapped.opp} として参照される商談と、{!oppWrapped.tabIndex} として参照されるその tabIndex をラップするオブジェクトのリストは反復処理します。次に、このコレクションを提供するコントローラを示します。
1swfobject.registerObject("clippy.codeblock-3", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class OppsController {
18
19 // Get a set of Opportunities
20 public ApexPages.StandardSetController setCon {
21 get {
22 if(setCon == null) {
23 setCon = new ApexPages.StandardSetController(Database.getQueryLocator(
24 [SELECT name, type, amount, closedate FROM Opportunity]));
25 setCon.setPageSize(5);
26 }
27 return setCon;
28 }
29 set;
30 }
31
32 public List<Opportunity> getOpportunities() {
33 return (List<Opportunity>) setCon.getRecords();
34 }
35
36 public List<OppWrapper> getOpportunitiesWithIndex() {
37 List<Opportunity> opps = this.getOpportunities();
38 List<OppWrapper> oppsWrapped = new List<OppWrapper>();
39 Integer idex = 1;
40 for (Opportunity opp : opps) {
41 oppsWrapped.add(new OppWrapper(opp, idex));
42 idex++;
43 }
44 return oppsWrapped;
45 }
46
47 public class OppWrapper {
48 public Opportunity opp { get; set; }
49 public Integer tabIndex { get; set; }
50 public OppWrapper(Opportunity opp, Integer tabIndex) {
51 this.opp = opp;
52 this.tabIndex = tabIndex;
53 }
54 }
55}- 内部クラス OppWrapper は商談への参照とインデックス番号を組み合わせます。
- getOpportunitesWithIndex メソッドは、それぞれの OppWrapper の tabIndex の位置を計算して OppWrapper のリストを作成します。