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() を使用します。

無料で学習を続けましょう!
続けるにはアカウントにサインアップしてください。
サインアップすると次のような機能が利用できるようになります。
  • 各自のキャリア目標に合わせてパーソナライズされたおすすめが表示される
  • ハンズオン Challenge やテストでスキルを練習できる
  • 進捗状況を追跡して上司と共有できる
  • メンターやキャリアチャンスと繋がることができる