動的コンポーネントの作成と表示
ページ上の 2 つの部分に動的 Visualforce コンポーネントを埋め込むことができます。
- ページの任意の場所に <apex:dynamicComponent> タグを追加する。このタグは、動的コンポーネントのプレースホルダとして機能します。
- コントローラまたはコントローラ拡張内の動的 Visualforce コンポーネントを開発する。
<apex:dynamicComponent> タグには、componentValue という必須属性が 1 つあります。この属性は、動的コンポーネントを返す Apex メソッドの名前を受け入れます。たとえば、送信フォームの期限が過ぎたら、異なるセクションヘッダーのタイトルを動的に生成したい場合、次のマークアップとコントローラコードを使用します。
1 ページに複数の <apex:dynamicComponent> コンポーネントを含めることができます。
1<apex:page standardController="Contact" extensions="DynamicComponentExample">
2 <apex:dynamicComponent componentValue="{!headerWithDueDateCheck}"/>
3 <apex:form>
4 <apex:inputField value="{!Contact.LastName}"/>
5 <apex:commandButton value="Save" action="{!save}"/>
6 </apex:form>
7</apex:page>1public class DynamicComponentExample {
2 public DynamicComponentExample(ApexPages.StandardController con) { }
3 public Component.Apex.SectionHeader getHeaderWithDueDateCheck() {
4 date dueDate = date.newInstance(2011, 7, 4);
5 boolean overdue = date.today().daysBetween(dueDate) < 0;
6
7 Component.Apex.SectionHeader sectionHeader = new Component.Apex.SectionHeader();
8 if (overdue) {
9 sectionHeader.title = 'This Form Was Due On ' + dueDate.format() + '!';
10 return sectionHeader;
11 } else {
12 sectionHeader.title = 'Form Submission';
13 return sectionHeader;
14 }
15 }
16}各動的コンポーネントには、一連の共通メソッドおよびプロパティへのアクセス権があります。この一覧を確認するには、『Apex 開発者ガイド』の「コンポーネントクラス」の章を参照してください。
動的カスタムコンポーネント
カスタムコンポーネントを動的に使用すると、標準 Visualforce コンポーネントとまったく同じ動作をします。名前空間がカスタムコンポーネントの名前空間に変わるだけです。カスタムコンポーネントは、c 名前空間にあるため、次のように動的に作成することができます。
1Component.c.MyCustomComponent myDy = new Component.c.MyCustomComponent();独自のコンポーネントの利便性のために、次のように名前空間を除外できます。
1Component.MyCustomComponent myDy = new Component.MyCustomComponent();サードパーティがパッケージで提供するコンポーネントを使用する場合は、パッケージプロバイダの名前空間を使用します。
1Component.TheirName.UsefulComponent usefulC = new Component.TheirName.UsefulComponent();コンストラクタを使用して属性を渡す
プロパティを使用してコンポーネントの属性を設定する代わりに、コンストラクタを使用して 1 つ以上の属性のリストを渡すことができます。
属性がコンストラクタに定義されていない場合、コンポーネントのデフォルト値がその属性に使用されます。
1Component.Apex.DataList dynDataList =
2 new Component.Apex.DataList(id='myDataList', rendered=true);プロパティを介してではなく、コンストラクタに属性を定義する必要があるコンポーネントが 2 つあります。
- レコードの Chatter 情報とコントロールを表示する場合、Component.Apex.Detail で、showChatter=true がそのコンストラクタに渡されている必要があります。それ以外の場合、この属性は常に false になります。
- ユーザが一度に複数のオプションを選択できるようにする場合は、Component.Apex.SelectList で、multiSelect=true がそのコンストラクタに渡されている必要があります。それ以外の場合、この値は常に false になります。
式および任意の HTML の定義
式の言語ステートメントを expressions プロパティを使用して追加できます。式のステートメントを渡すには、プロパティ名の前に expressions を付加します。静的マークアップと同様に、式は {! } 構文でラップする必要があります。次に例を示します。
1Component.Apex.Detail detail = new Component.Apex.Detail();
2detail.expressions.subject = '{!Account.ownerId}';
3detail.relatedList = false;
4detail.title = false;有効な式には、標準オブジェクトやカスタムオブジェクトの項目を参照する式などがあります。次の例のようにグローバル変数と関数も使用できます。
1Component.Apex.OutputText head1 = new Component.Apex.OutputText();
2head1.expressions.value =
3 '{!IF(CONTAINS($User.FirstName, "John"), "Hello John", "Hey, you!")}';式で値を渡すのは、それをサポートする属性でのみ有効です。expressions プロパティ以外で {! } を使用すると、式ではなく文字として解釈されます。
プレーン HTML を含めるには、Component.Apex.OutputText の escape プロパティを false に設定します。
1Component.Apex.OutputText head1 = new Component.Apex.OutputText();
2head1.escape = false;
3head1.value = '<h1>This header contains HTML</h1>';ファセットの定義
式を定義する方法と同様に、ファセットは動的コンポーネントが使用できる特殊なプロパティとして機能します。次に例を示します。
1Component.Apex.DataTable myTable = new Component.Apex.DataTable(var='item');
2myTable.expressions.value = '{!items}';
3Component.Apex.OutputText header =
4 new Component.Apex.OutputText(value='This is My Header');
5myTable.facets.header = header;ファセットについての詳細は、「コンポーネントファセットの使用のためのベストプラクティス」を参照してください。
子ノードの定義
childComponents プロパティを使用して、子ノードを動的 Visualforce コンポーネントに追加できます。childComponents プロパティは Component.Apex オブジェクトのリストへの参照として機能します。
次の例では、childComponents を使用して子入力ノードで <apex:form> を構築する方法を示します。
1public Component.Apex.PageBlock getDynamicForm() {
2 Component.Apex.PageBlock dynPageBlock = new Component.Apex.PageBlock();
3
4 // Create an input field for Account Name
5 Component.Apex.InputField theNameField = new Component.Apex.InputField();
6 theNameField.expressions.value = '{!Account.Name}';
7 theNameField.id = 'theName';
8 Component.Apex.OutputLabel theNameLabel = new Component.Apex.OutputLabel();
9 theNameLabel.value = 'Rename Account?';
10 theNameLabel.for = 'theName';
11
12 // Create an input field for Account Number
13 Component.Apex.InputField theAccountNumberField = new Component.Apex.InputField();
14 theAccountNumberField.expressions.value = '{!Account.AccountNumber}';
15 theAccountNumberField.id = 'theAccountNumber';
16 Component.Apex.OutputLabel theAccountNumberLabel = new Component.Apex.OutputLabel();
17 theAccountNumberLabel.value = 'Change Account #?';
18 theAccountNumberLabel.for = 'theAccountNumber';
19
20 // Create a button to submit the form
21 Component.Apex.CommandButton saveButton = new Component.Apex.CommandButton();
22 saveButton.value = 'Save';
23 saveButton.expressions.action = '{!Save}';
24
25 // Assemble the form components
26 dynPageBlock.childComponents.add(theNameLabel);
27 dynPageBlock.childComponents.add(theNameField);
28 dynPageBlock.childComponents.add(theAccountNumberLabel);
29 dynPageBlock.childComponents.add(theAccountNumberField);
30 dynPageBlock.childComponents.add(saveButton);
31
32 return dynPageBlock;
33}マークアップが次のように定義されている場合:
このマークアップは次の静的マークアップに相当します。
同等の静的マークアップでの要素の順序は、動的コンポーネントが getDynamicForm メソッドの Apex コ��ドで宣言された順序ではなく、childComponents に追加された順序です。
1<apex:form>
2 <apex:dynamicComponent componentValue="{!dynamicForm}"/>
3</apex:form>1<apex:form>
2 <apex:pageBlock>
3 <apex:outputLabel for="theName"/>
4 <apex:inputField value="{!Account.Name}" id="theName"/>
5 <apex:outputLabel for="theAccountNumber"/>
6 <apex:inputField value="{!Account.AccountNumber}" id="theAccountNumber"/>
7 <apex:commandButton value="Save" action="{!save}"/>
8 </apex:pageBlock>
9</apex:form>