1

I am considering to build a Classic app which should consist of 5 to 10 tabs, each one containing single LWC component (single different LWC component).

I want to avoid code duplication and don't want to create multiple containers.

I would like to use as few reusable containers as possible.

I am looking for the most efficient solution in terms the least amount of containers possible in the current Spring '19 Release.

So far I was considering the following approach (which doesn't work completely)

I could create a standalone Lightning App LWCContainer.app with the following code

<aura:application extends="force:slds">
    <aura:attribute name="cmpName" type="String" default="lightning:button"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    Dynamic content here: <br/><br/>
    {!v.body} 
</aura:application> 

and the controller

({
    doInit : function(cmp) {
        $A.createComponent(
            cmp.get("v.cmpName"),
            {
            },
            function(newButton, status, errorMessage){

                if (status === "SUCCESS") {
                    var body = cmp.get("v.body");
                    body.push(newButton);
                    cmp.set("v.body", body);
                }
                else if (status === "INCOMPLETE") {
                    console.log("No response from server or client is offline.")
                    // Show offline error
                }
                else if (status === "ERROR") {
                    console.log("Error: " + errorMessage);
                    // Show error message
                }
            }
        );
    }
})

and then I could create a Web Tab with link /c/LWCContainer.app?cmpName=c:fls and a Web Tab with link /c/LWCContainer.app?cmpName=c:ols so that I would need n or O(n) of Web Tabs and 1 or O(1) of custom Lightning App containers, whene n is the number of Tabs or LWC components I would like to expose as tabs.

However, this approach actually doesn't work due to inability of containing Lightning standalone apps or other Lightning components inside of iframes which is generating error

Refused to display 'https://flsman-dev-ed.lightning.force.com/c/LWCContainer.app?cmpName=c:fls' in a frame because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self'".

enter image description here


Update: source code for two LWC components mentioned above.

lwc/fls/fls.html

<template>
    FLS!
    <br/>
    FLS 
</template>

lwc/fls/fls.js

import { LightningElement } from 'lwc';

export default class Fls extends LightningElement {}

lwc/fls/fls.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="fls">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

lwc/ols/ols.html

<template>
    OLS!
</template>

lwc/ols/ols.js

import { LightningElement } from 'lwc';

export default class Ols extends LightningElement {}

lwc/ols/ols.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="fls">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>
  • I think you are referring Lighting Aura Components and not Lightning Web Components (LWC), correct? LWC as of now is not supposed in Lightning Out. If that's the correct understanding, you may like to edit your post. – Jayant Das Feb 19 '19 at 20:40
  • @JayantDas, no I actually refer to Lightning Web Components. I use Lightning Out Container as a middle layer between the tab and the Lightning Web Components. – Patlatus Feb 19 '19 at 20:47
  • Okay, because I didn't see an example as how LWC is tied to your Aura component, so was confused. You may probably like to add a LWC as an example in your question/answer to make it more clear? – Jayant Das Feb 19 '19 at 20:51
  • I have updated my question to display the code for LWC components. However, they are irrelevant mostly here, their code is just dummy placeholder, the first component contains duplicated "FLS" string separated by horizontal break while the second component contains "OLS" string literal. – Patlatus Feb 19 '19 at 20:57
  • Thanks. The only reason I asked to help someone like me who may get confused by thinking c:fls as an aura component! :) – Jayant Das Feb 19 '19 at 20:58
3

I think I have found the following solution which would require n tabs and 1 Visualforce page with 1 Lightning Out Container app.

Web tabs will have relative URLS referring to different LWC components like /apex/LWCCont?cmpName=c:fls or /apex/LWCCont?cmpName=c:ols.

Visualforce page will have the following code

<apex:page controller="LWCContController" sidebar="false">
    <apex:includeLightning />

    <div id="lightning" />

    <script>
        $Lightning.use("c:lwcOut",    // name of the Lightning app
            function() {                  // Callback once framework and app loaded
                $Lightning.createComponent(
                    "{!cmpName}", // top-level component of your app
                    { },                  // attributes to set on the component when created
                    "lightning",   // the DOM location to insert the component
                    function(cmp) {
                        // callback when component is created and active on the page
                    }
                );
            }
        );
    </script>
</apex:page>

with Apex Controller

public inherited sharing class LWCContController {

    public String cmpName { get{
        return ApexPages.currentPage().getParameters().get('cmpName');
    } set; }
}

Also lwcOut.app will contain code of dummy lightning-out app

<aura:application access="GLOBAL" extends="ltng:outApp"> 
</aura:application> 

In total, this approach would need 3 custom container-related component to serve any number of LWC components to be exposed ( 1 Apex Class, 1 Visualforce Page, 1 Lightning Out Standalone App).

One drawback of this approach that on switching tab currently selected tab is not marked as selected which is disappointing. However, I don't know how to fix that.

enter image description here

enter image description here

If someone finds more elegant or sophisticated solution please share.

| improve this answer | |

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.