7

In Visualforce, it is possible to have multiple layouts on one page. The "rendered" attribute can be used to display the relevant layout as needed. Typically, a user will navigate thru each layout by clicking on a command button which calls an Apex controller class; the Apex controller class will set the data for the next page, set the variables which control the rendering, and then return a null page reference to force the page to be redrawn. What is the best practice to do something similar in Lightning, specifically for those cases where the logic to control the data is in the Apex controller class?

8

Lightning gives us the freedom to do things the way we want. There are three typical methods for rendering a UI, and all three are recommended by the documentation. It's usually a matter of preference which way you'd like to go.

aura:if

Use aura:if to render sections based on a Boolean attribute. This method is slightly slower than rendering yourself, but requires slightly less code than rendering components yourself. Use this when there's not a complicated layout and only a handful of possible outcomes.

<aura:if isTrue="{!...}">
  ...
  <aura:set attribute="else">
    ...
  </aura:set>
</aura:if>
...

CSS

Lightning gives us a useful CSS style, slds-hide, which allows us to hide a component without actually destroying/creating it anew. Typically, you probably don't want to do this, because even hidden, components have to respond to events like aura:valueChange, so there may be a notable increase in response time on larger components, but it may be acceptable to use as an alternative to aura:if if there's a lot of render time going on.

<div class="{!v.className}">
  ...
</div>

...

component.set("v.className", "slds-hide"); // To hide something
...
component.set("v.className",""); // To show something

$A.createComponents

The third option is to have an attribute (we can use body if we like, but using a separate one might be useful), and create our components ourselves:

<aura:attribute name="content" type="Aura.Component[]" default="[]" />
{!v.content}

...

var action = component.get("c.someAction");
action.setCallback(this, response => {
  $A.createComponents(
    response.getReturnValue(),
    components => component.set("v.content", components)
  );
});
$A.enqueueAction(action);

Note that setCallback here is literally just parsing return data from the server, but you can also put more advanced logic in here as well. Note that setting a component facet (an attribute of Aura.Component[]) automatically destroys any previous components that were already stored in the attribute. This method is preferred when you need to create many components dynamically, but requires a bit more controller code.

  • I guess this raises another question I hadn't previously thought of. As I said above, a VF page can have multiple "layouts" - using something like apex:outputPanel - with the appropriate ones hidden/displayed as needed. In Lightning, would it be considered "best practice" to use an individual Lightning component for each "layout"? What about the case where you are doing the equivalent of a VF "wizard", where you collect the required data on multiple layouts and then save all the data at the end? – hamayoun May 2 '18 at 17:09
  • @hamayoun The choice to use components, or not, is somewhat arbitrary. Unless the layout sections were to be used in other components, you don't gain much, since the main point of components is reusability. At minimum, using aura:if as a drop-in replacement for aura:outputPanel/apex:outputText with rendering control would work just fine; sections of the page can be dynamically created and destroyed just like in Visualforce. Whether or not it's worth the effort to make each section its own component is mostly based on intent; do you intend to use those sections again elsewhere? – sfdcfox May 2 '18 at 17:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.