Skip to main content

Compartir páginas de Visualforce entre Classic y Lightning Experience

Objetivos de aprendizaje

Después de completar esta unidad, podrá:
  • Enumerar dos beneficios de compartir páginas entre Salesforce Classic y Lightning Experience.
  • Describir la diferencia entre el contexto de la interfaz de usuario solicitada por el usuario, y el contexto de la interfaz de usuario donde el usuario realmente está.
  • Describir tres maneras diferentes de probar y determinar el contexto de la interfaz de usuario del usuario actual.

Compartir páginas de Visualforce entre Classic y Lightning Experience

Recomendamos que, siempre que sea posible, cree páginas de Visualforce que se comporten correctamente cuando se ejecuten en Salesforce Classic o Lightning Experience. Los beneficios en el contexto de una complejidad reducida en el código y la configuración de su organización saltan a la vista. Y existen un número de contextos, como las sustituciones de Visualforce de las acciones estándar donde no tiene elección. Una sustitución de acción siempre utiliza la misma página, ya se esté ejecutando en Salesforce Classic, Lightning Experience o la aplicación Salesforce.

No obstante, es perfectamente razonable desear un comportamiento o estilo ligera o significativamente diferente en el contexto de la experiencia de usuario en el que se está ejecutando la página. En esta unidad trataremos la diversidad de formas de crear páginas que funcionan correctamente en todas las experiencias de usuario, y cómo su código puede detectar y realizar cambios para contextos específicos.

Detección y respuesta al contexto de la experiencia de usuario en marcas de Visualforce

Utilice las variables globales $User.UITheme y $User.UIThemeDisplayed para determinar el contexto de la experiencia de usuario actual. Puede utilizar estas variables en expresiones de Visualforce para adaptar sus páginas a Lightning Experience, Salesforce Classic y la aplicación Salesforce.
Estas variables globales devuelven una cadena que identifica exclusivamente el contexto de la interfaz de usuario actual. Los valores posibles para $User.UITheme y $User.UIThemeDisplayed son los mismos:
  • Theme1: Tema obsoleto de Salesforce
  • Theme2: Tema de la interfaz de usuario Salesforce Classic 2005
  • Theme3: Tema de la interfaz de usuario Salesforce Classic 2010
  • Theme4d: Tema moderno “Lightning Experience” de Salesforce
  • Theme4t: Tema de la aplicación móvil Salesforce
  • Theme4u: Tema de la Consola Lightning
  • PortalDefault: Tema del portal de clientes de Salesforce
  • Webstore: Tema de AppExchange de Salesforce
La diferencia entre las dos variables es que $User.UITheme devuelve el aspecto que se supone que debe ver el usuario, mientras que $User.UIThemeDisplayed devuelve el aspecto que el usuario ve realmente. Por ejemplo, puede que un usuario tenga la preferencia y los permisos para ver el aspecto de Lightning Experience, pero si está utilizando un navegador que no admite ese aspecto y comportamiento, como por ejemplo las versiones obsoletas de Internet Explorer, $User.UIThemeDisplayed devolverá un valor diferente. En general, su código debería utilizar $User.UIThemeDisplayed.
La manera más sencilla de utilizar estas variables globales de temas es utilizar una expresión booleana, como {! $User.UIThemeDisplayed == "Theme3" }, en el atributo rendered de un componente. El componente solo se mostrará si la página aparece en el contexto de la interfaz de usuario que desea.
<apex:outputText value="This is Salesforce Classic."
    rendered="{! $User.UIThemeDisplayed() == 'Theme3' }"/>
Aunque puede utilizar esta técnica en elementos individuales de la interfaz de usuario, es normalmente más eficiente si encierra las partes más grandes de las marcas en un <apex:outputPanel> u otro componente de nivel de bloques similar y luego crea bloques separados para cada interfaz de usuario diferente que desee presentar. A continuación, coloque la prueba de tema en el atributo rendered de los bloques en vez de hacerlo en los componentes individuales. Esto no solo tiene un mejor desempeño, si no que también su código es menos complicado.
<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>
Otra estrategia con la que puede utilizar este método es seleccionar de forma dinámica una hoja de estilo para incluir en su página, y proporcionar una hoja de estilo diferente para cada tema. Esto es un poco más difícil de lo que pueda pensar, ya que la etiqueta <apex:stylesheet> no tiene un atributo rendered propio. En ese caso, debe encerrar los componentes de la hoja de estilo dentro de otro componente que tenga el atributo rendered. A continuación se muestra un ejemplo de cómo proporcionar una hoja de estilo diferente para cada uno de los tres temas modernos que se admiten en Salesforce.
<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>

Más allá de los fundamentos

Esta es una forma poco habitual de utilizar <apex:variable>, porque no estamos realmente interesados en el valor de la variable creada. En su lugar solo queremos un componente que no represente ningún resultado propio para encerrar el componente <apex:stylesheet>. Puede pensar en esto como un componente <apex:variable> que “presta” su atributo rendered al componente <apex:stylesheet> encerrado.

Es bastante bueno que no nos importe la variable en sí, porque otro aspecto poco habitual de encerrar el componente <apex:variable> dentro de otra cosa es que la variable no se crea realmente. ¿Característica o fallo? Llamémoslo... comportamiento indefinido, y evite utilizar la variable uiTheme en otro lugar.

Detección y respuesta al contexto de la experiencia de usuario en JavaScript

La detección del contexto de la experiencia de usuario actual en código JavaScript es importante si utiliza mucho JavaScript en sus páginas y aplicaciones. Es de especial importancia utilizar la técnica correcta para gestionar la navegación en su código JavaScript.

Para detectar lo que el usuario ve en JavaScript, utilizamos un método similar para la determinación del contexto de experiencia de usuario actual en Visualforce. Llame la variable global UITheme.getUITheme() para devolver un valor que identifica el tema de la interfaz de usuario actual.

Aquí, el código comprueba si el contexto de experiencia de usuario actual es el tema Lightning Experience.

function isLightningDesktop() {
  return UITheme.getUITheme === "Theme4d";
}

Determinación del contexto de la experiencia de usuario en Apex

Utilice los métodos del sistema UserInfo.getUiTheme() y UserInfo.getUiThemeDisplayed() para determinar la el contexto de la experiencia de usuario actual en el código Apex. Puede utilizarlos cuando los métodos o propiedades de acciones del controlador tengan que comportarse de manera diferente en contextos diferentes.
El siguiente ejemplo ilustra cómo utilizar estos métodos dejándolos disponibles a través de métodos de obtención en una extensión de controlador.
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();
    }
}
También podría trabajar con los valores en su código Apex, en vez de hacerlo directamente devolviendo los resultados de la llamada de método.
Estos métodos del sistema de Apex devuelven una cadena que identifica exclusivamente el contexto de la interfaz de usuario actual. Los valores posibles devueltos por estos métodos son los mismos que los que devuelven las variables globales $User.UITheme y $User.UIThemeDisplayed.
  • Theme1: Tema obsoleto de Salesforce
  • Theme2: Tema de la interfaz de usuario Salesforce Classic 2005
  • Theme3: Tema de la interfaz de usuario Salesforce Classic 2010
  • Theme4d: Tema moderno “Lightning Experience” de Salesforce
  • Theme4t: Tema de la aplicación móvil Salesforce
  • Theme4u: Tema de la Consola Lightning
  • PortalDefault: Tema del portal de clientes de Salesforce
  • Webstore: Tema de AppExchange de Salesforce

El uso de estos métodos en el código del controlador del lado del servidor debería ser escaso, al menos en comparación con proporcionar marcas de Visualforce diferentes o código JavaScript. Es una mejor práctica para su controlador y el código de la extensión del controlador que sean neutros en lo referente al contexto UX. Deje que el código de su extremo delantero, ya sea Visualforce o JavaScript, controle las diferencias de la interfaz de usuario.

Consultas de Lightning Experience a través del acceso de SOQL y API

Aunque no recomendamos esta técnica, puede consultar la experiencia de usuario preferida del usuario actual empleando directamente SOQL.
La consulta SOQL básica es la siguiente.
SELECT UserPreferencesLightningExperiencePreferred FROM User WHERE Id = 'CurrentUserId'
El resultado es un valor de preferencia sin procesar, que necesita para convertirlo en algo utilizable.
A continuación se muestra la página más sencilla de Visualforce que se ejecuta encima de la consulta SOQL y muestra el resultado en la página.
<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>

No recomendamos realizar consultas directas de la preferencia de Lightning Experience del usuario. El resultado le indica cuál es el parámetro de preferencia actual del usuario, no la experiencia de usuario que hay en pantalla en ese momento. Existen varios casos de uso donde el valor de preferencia puede no reflejar la experiencia de usuario que se está entregando en esos momentos. Para determinar la experiencia de usuario actual que se está entregando en la solicitud actual, utilice $User.UIThemeDisplayed o UserInfo.getUiThemeDisplayed().

Comparta sus comentarios de Trailhead en la Ayuda de Salesforce.

Nos encantaría saber más sobre su experiencia con Trailhead. Ahora puede acceder al nuevo formulario de comentarios en cualquier momento en el sitio de Ayuda de Salesforce.

Más información Continuar a Compartir comentarios