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'".
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>
Best Answer
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
with Apex Controller
Also
lwcOut.app
will contain code of dummy lightning-out appIn 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.
If someone finds more elegant or sophisticated solution please share.