Classic と Lightning Experience 間での Visualforce ページの共有
学習の目的
この単元を完了すると、次のことができるようになります。
- Salesforce Classic と Lightning Experience 間でページを共有するメリットを 2 つ挙げる。
- ユーザーに要求されたユーザーインターフェースコンテキストと、ユーザーの実際のユーザーインターフェースコンテキストの違いを説明する。
- 現在のユーザーのユーザーインターフェースコンテキストをテストして判別する 3 種類の方法を説明する。
Classic と Lightning Experience 間の Visualforce ページの共有
可能な限り、Salesforce Classic で実行しても Lightning Experience で実行しても正しく動作する Visualforce ページを作成することをお勧めします。こうしたページを作成すれば、組織のコードや設定の複雑性が緩和されるという明白なメリットがあります。また、Visualforce による標準アクションの上書きなど、選択するまでもなく同じページが使用される状況も多々あります。override アクションは、Salesforce Classic、Lightning Experience、Salesforce アプリケーションのどれで実行しているかに関係なく、常に同じページを使用します。
とはいえ、ページを実行しているユーザーエクスペリエンスコンテキストに応じて動作やスタイル設定をわずかに、あるいは大幅に変えたいと思う状況も当然ながら存在します。この単元では、すべてのユーザーエクスペリエンスで正しく機能するページを作成するさまざまな方法と、コードで特定のコンテキストを検出して変更する方法を見ていきます。
Visualforce マークアップでのユーザーエクスペリエンスコンテキストの検出と対応
現在のユーザーエクスペリエンスコンテキストを判別するには、$User.UITheme および $User.UIThemeDisplayed グローバル変数を使用します。これらの変数を Visualforce 式で使用して、ページを Lightning Experience、Salesforce Classic、および Salesforce アプリケーションに適応させることができます。
次のグローバル変数では、現在のユーザーインターフェースコンテキストを一意に識別する文字列を返します。$User.UITheme と $User.UIThemeDisplayed の有効値は同じです。
- Theme1 — 古い Salesforce テーマ
- Theme2 — Salesforce Classic 2005 ユーザーインターフェースのテーマ
- Theme3 — Salesforce Classic 2010 ユーザーインターフェースのテーマ
- Theme4d — 最新の「Lightning Experience」 Salesforce のテーマ
- Theme4t — Salesforce モバイルアプリケーションのテーマ
- Theme4u — Lightning コンソールのテーマ
- PortalDefault — Salesforce カスタマーポータルのテーマ
- Webstore — Salesforce AppExchange のテーマ
これら 2 つの変数は、$User.UITheme がユーザーに表示すべきデザインを返し、$User.UIThemeDisplayed が実際のデザインを返すという点で異なります。たとえば、ユーザーは Lightning Experience のデザインを表示する設定と権限を持っている場合がありますが、そのデザインをサポートしていないブラウザーを使用していると、旧バージョンの Internet Explorer などで $User.UIThemeDisplayed が異なる値を返す場合があります。一般に、コードでは $User.UIThemeDisplayed を使用する必要があります。
このようなテーマグローバルを使用する最も簡単な方法は、コンポーネントの rendered 属性の Boolean 式で使用することです ({! $User.UIThemeDisplayed == "Theme3" } など)。このコンポーネントは、目的のユーザーインターフェースコンテキストでページが表示された場合にのみ表示されます。
<apex:outputText value="This is Salesforce Classic." rendered="{! $User.UIThemeDisplayed() == 'Theme3' }"/>
この手法は、個々のユーザーインターフェース要素で使用できますが、通常は、より大きいマークアップのチャンクを <apex:outputPanel> または類似のブロックレベルコンポーネントでラップして、表示するさまざまな UI ごとに別個のブロックを作成するとより効率的です。その後で、個々のコンポーネントではなく、ブロックの rendered 属性に対してテーマテストを配置します。この方がパフォーマンスがよいだけでなく、コードが簡素化されます。
<apex:outputPanel rendered="{! $User.UIThemeDisplayed == 'Theme3' }"> <apex:outputText value="This is Salesforce Classic."/> <apex:outputText value="These are multiple components wrapped by an outputPanel."/> </apex:outputPanel> <apex:outputPanel rendered="{! $User.UIThemeDisplayed == 'Theme4d' }"> <apex:outputText value="Everything is simpler in Lightning Experience."/> </apex:outputPanel>
これに使用できるもう 1 つの戦略は、ページに含めるスタイルシートを動的に選択し、テーマごとに異なるスタイルシートを指定することです。<apex:stylesheet> タグ自体には rendered 属性がないため、これには少しコツがいります。この場合、スタイルシートコンポーネントを、rendered 属性を持つ別のコンポーネントでラップする必要があります。次の例では、Salesforce でサポートされている最新の 3 つのテーマのそれぞれに異なるスタイルシートを指定する方法を示します。
<apex:page standardController="Account"> <!-- Salesforce Classic "Aloha" theme --> <apex:variable var="uiTheme" value="classic2010Theme" rendered="{!$User.UIThemeDisplayed == 'Theme3'}"> <apex:stylesheet value="{!URLFOR($Resource.AppStyles, 'classic-styling.css')}" /> </apex:variable> <!-- Lightning Desktop theme --> <apex:variable var="uiTheme" value="lightningDesktop" rendered="{!$User.UIThemeDisplayed == 'Theme4d'}"> <apex:stylesheet value="{!URLFOR($Resource.AppStyles, 'lightning-styling.css')}" /> </apex:variable> <!-- Salesforce mobile theme --> <apex:variable var="uiTheme" value="SalesforceApp" rendered="{!$User.UIThemeDisplayed == 'Theme4t'}"> <apex:stylesheet value="{!URLFOR($Resource.AppStyles, 'mobile-styling.css')}" /> </apex:variable> <!-- Rest of your page --> <p> Value of $User.UIThemeDisplayed: {! $User.UIThemeDisplayed } </p> </apex:page>
高度な操作
これは、作成された変数の値を使用しないため、<apex:variable> の使用方法としては普通ではありません。他にも、独自の出力を表示しないコンポーネントであれば、<apex:stylesheet> コンポーネントをラップできます。この方法は、<apex:variable> が、ラップされている <apex:stylesheet> コンポーネントにその rendered 属性を「貸している」ようなものだと考えてください。
<apex:variable> コンポーネントで他のコンポーネントをラップする場合、変数そのものは使用しないことをお勧めします。変数は実際には作成されないからです! これは機能なのか、それともバグなのか? とりあえず未定義の動作と呼びましょう。そして他の場所で uiTheme 変数を使用するのは避けてください。
JavaScript でのユーザーエクスペリエンスコンテキストの検出と応答
ページやアプリケーションで JavaScript を多用している場合は、JavaScript コード内で現在のユーザーエクスペリエンスコンテキストを検出することが重要です。これは特に、適切な方法を使用して JavaScript コード内のナビゲーションを管理するために重要です。
ユーザーに表示されている内容を JavaScript で検出するには、Visualforce で現在のユーザーエクスペリエンスコンテキストを検出するのと似た方法を使用します。UITheme.getUITheme() グローバル変数をコールして、現在のユーザーインターフェーステーマを識別する値を返します。
次のコードは、現在のユーザーエクスペリエンスコンテキストが Lightning Experience テーマかどうかを確認します。
function isLightningDesktop() { return UITheme.getUITheme === "Theme4d"; }
Apex でのユーザーエクスペリエンスコンテキストの判定
Apex コード内で現在のユーザーエクスペリエンスコンテキストを判定するには、UserInfo.getUiTheme() および UserInfo.getUiThemeDisplayed() システムメソッドを使用します。コントローラーアクションメソッドやプロパティがコンテキストに応じて異なる動作をする必要がある場合に使用できます。
次の例は、これらのメソッドを使用するために、コントローラー拡張内の getter メソッドを通じてこれらのメソッドを使用できるようにする方法を示しています。
public with sharing class ForceUIExtension { // Empty constructor, required for Visualforce controller extension public ForceUIExtension(ApexPages.StandardController controller) { } // Simple accessors for the System.UserInfo theme methods public String getContextUserUiTheme() { return UserInfo.getUiTheme(); } public String getContextUserUiThemeDisplayed() { return UserInfo.getUiThemeDisplayed(); } }
もちろん、メソッドのコールの結果を直接返さずに、Apex コード内で値を処理することもできます。
これらの Apex システムメソッドは、現在のユーザーインターフェースコンテキストを一意に識別する文字列を返します。これらのメソッドによって返される可能性のある値は、$User.UITheme および $User.UIThemeDisplayed グローバル変数によって返される値と同じです。
- Theme1 — 古い Salesforce テーマ
- Theme2 — Salesforce Classic 2005 ユーザーインターフェースのテーマ
- Theme3 — Salesforce Classic 2010 ユーザーインターフェースのテーマ
- Theme4d — 最新の「Lightning Experience」 Salesforce のテーマ
- Theme4t — Salesforce モバイルアプリケーションのテーマ
- Theme4u — Lightning コンソールのテーマ
- PortalDefault — Salesforce カスタマーポータルのテーマ
- Webstore — Salesforce AppExchange のテーマ
これらのメソッドをサーバー側のコントローラーコードで使用することはまれで、異なる Visualforce マークアップまたは JavaScript コードを提供する方が一般的です。コントローラーおよびコントローラー拡張コードは UX コンテキストに関して中立にすることがベストプラクティスです。ユーザーインターフェースの違いは、Visualforce であっても JavaScript であってもフロントエンドコードで処理することをお勧めします。
SOQL および API アクセスを使用した Lightning Experience のクエリ
SOQL を使用して現在のユーザーが選好するユーザーエクスペリエンスを直接照会することができますが、この方法はお勧めしません。
基本的な SOQL クエリは次のとおりです。
SELECT UserPreferencesLightningExperiencePreferred FROM User WHERE Id = 'CurrentUserId'
この結果は未加工の選好値のため、何らかの使用可能な値に変換する必要があります。
次に、上記の SOQL クエリを実行して結果をページに表示するごくシンプルな Visualforce ページを示します。
<apex:page> <script src="/soap/ajax/36.0/connection.js" type="text/javascript"></script> <script type="text/javascript"> // Query for the preference value sforce.connection.sessionId = '{! $Api.Session_ID }'; var uiPrefQuery = "SELECT Id, UserPreferencesLightningExperiencePreferred " + "FROM User WHERE Id = '{! $User.Id }'"; var userThemePreferenceResult = sforce.connection.query(uiPrefQuery); // Display the returned result on the page document.addEventListener('DOMContentLoaded', function(event){ document.getElementById('userThemePreferenceResult').innerHTML = userThemePreferenceResult; }); </script> <h1>userThemePreferenceResult (JSON)</h1> <pre><span id="userThemePreferenceResult"/></pre> </apex:page>
ユーザーの Lightning Experience の選好を直接照会することはお勧めしません。結果からわかるのはユーザーが現在選好する設定で、画面上の実際のユーザーエクスペリエンスではありません。いくつかのユースケースでは、実際に行われているユーザーエクスペリエンスが選好値に反映されない場合があります。現在の要求で実際に行われているユーザーエクスペリエンスを判別するには、$User.UIThemeDisplayed または UserInfo.getUiThemeDisplayed() を使用します。
リソース
- $User.UITheme と $User.UIThemeDisplayed
- UserInfo クラス
- Visualforce 開発者ガイド
- 記事: Developing Cross-Device HTML5 Apps Using Visualforce (Visualforce を使用したクロスデバイス HTML5 アプリケーションの開発)