Lightning Web Components Quick Action workaround - highly flexible
Lightning Web Components do not support quick action, to create one we need to wrap the LWC into an aura LC, this is good for many use cases where there is not much customization required on the UI especially with the with of the modal.
In case where we need a bigger modal, we used workarounds like the below
http://www.sfdcbox.com/2018/07/customize-width-header-and-footer-for.html
But, a similar workaround with the LWCs is not working with the known issue on css side where the component in absolute position and its child elements see scroll issues. especially with LWCs I have observed that mouse scroll wheel has no effect on the scroll bar.
Below is a workaround using the Pub/Sub published in the recipes app
1. Copy auraPubsub and pubsub
2. Create an aura lightning component
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickActionWithoutHeader" access="global">
<c:auraPubsub aura:id="pubsub" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<div class="slds-text-align_center slds-text-heading_medium">Modal Header</div>
</aura:component>
//the js controller
({
doInit : function(component, event, helper) {
window.setTimeout(
$A.getCallback(function() {
$A.get("e.force:closeQuickAction").fire();
var pubsub = component.find('pubsub');
pubsub.fireEvent('openModal', 'any related message');
}), 0
);
}
})
3. Create the Lightning Web Component modal lwcModal
lwcModal.html
<template>
<template if:true={openModal}>
<div role="dialog" tabindex="-1" class={modalClass} aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1">
<template if:false={loaded}>
<lightning-spinner alternative-text="Loading"></lightning-spinner>
</template>
<div class="slds-modal__container">
<header class="slds-modal__header">
<lightning-button-icon class="slds-modal__close" size="large" icon-name="utility:close" onclick={closeModal} variant="bare-inverse" alternative-text="close"></lightning-button-icon>
<h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Modal Header</h2>
</header>
<div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1" style=" padding-top: .25rem; ">
Mobal Body Mobal Body Mobal Body Mobal Body Mobal Body
</div>
<footer class="slds-modal__footer">
<lightning-button label="Close" title="Close" onclick={closeModal} class="slds-m-left_x-small"></lightning-button>
<lightning-button variant="brand" label="Save" title="save" class="slds-m-left_x-small"></lightning-button>
</footer>
</div>
</div>
<div class="slds-backdrop slds-backdrop_open"></div>
</template>
</template>
lwcModal.js
import { LightningElement, api, wire, track } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { CurrentPageReference } from 'lightning/navigation';
import { registerListener, unregisterAllListeners } from 'c/pubsub';
import getModalBody from '@salesforce/apex/lwcModalApex.getModalBody';
export default class LwcModal extends LightningElement {
@wire(CurrentPageReference) pageRef;
@api recordId;
@track loaded = false;
@track openModal = false;
@track error;
@track modalBody;
get modalClass(){
return this.openModal?'slds-modal slds-modal_large slds-fade-in-open':'slds-modal slds-modal_large';
}
handleLoad(){
getModalBody({rId : this.recordId})
.then(result => {
this.modalBody = result;
this.error = undefined;
this.loaded = true;
this.openModal = true;
})
.catch(error => {
this.error = error;
this.loaded = true;
this.showNotification('Error', error.body.message, 'error');
this.closeModal();
});
}
closeModal(){
this.openModal = false;
}
connectedCallback() {
registerListener('openModal', this.handleLoad, this);
}
disconnectedCallback() {
unregisterAllListeners(this);
}
showNotification(t,m,v) {
const evt = new ShowToastEvent({
title: t,
message: m,
variant: v
});
this.dispatchEvent(evt);
}
}
lwcModal.css
.slds-modal__content{
min-height: 15rem;
}
Apex Class
public class lwcModalApex {
@AuraEnabled(cacheable=true)
public static String getModalBody() {
return 'Modal body, Create anything as per the requirement, a huge complex wrapper may be :) ';
}
}
4. Finally and most importantly add the lwcModal component to the lightning page. remember pub/sub will only work b/w components on the same page, and this whole idea is to create a quick action which fires a publish event and closes itself the Lightning web Component which has subscribed for this event opens itself when it listens to the event published by the lightning component.
In case where we need a bigger modal, we used workarounds like the below
http://www.sfdcbox.com/2018/07/customize-width-header-and-footer-for.html
But, a similar workaround with the LWCs is not working with the known issue on css side where the component in absolute position and its child elements see scroll issues. especially with LWCs I have observed that mouse scroll wheel has no effect on the scroll bar.
Below is a workaround using the Pub/Sub published in the recipes app
1. Copy auraPubsub and pubsub
2. Create an aura lightning component
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickActionWithoutHeader" access="global">
<c:auraPubsub aura:id="pubsub" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<div class="slds-text-align_center slds-text-heading_medium">Modal Header</div>
</aura:component>
//the js controller
({
doInit : function(component, event, helper) {
window.setTimeout(
$A.getCallback(function() {
$A.get("e.force:closeQuickAction").fire();
var pubsub = component.find('pubsub');
pubsub.fireEvent('openModal', 'any related message');
}), 0
);
}
})
3. Create the Lightning Web Component modal lwcModal
lwcModal.html
<template>
<template if:true={openModal}>
<div role="dialog" tabindex="-1" class={modalClass} aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1">
<template if:false={loaded}>
<lightning-spinner alternative-text="Loading"></lightning-spinner>
</template>
<div class="slds-modal__container">
<header class="slds-modal__header">
<lightning-button-icon class="slds-modal__close" size="large" icon-name="utility:close" onclick={closeModal} variant="bare-inverse" alternative-text="close"></lightning-button-icon>
<h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Modal Header</h2>
</header>
<div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1" style=" padding-top: .25rem; ">
Mobal Body Mobal Body Mobal Body Mobal Body Mobal Body
</div>
<footer class="slds-modal__footer">
<lightning-button label="Close" title="Close" onclick={closeModal} class="slds-m-left_x-small"></lightning-button>
<lightning-button variant="brand" label="Save" title="save" class="slds-m-left_x-small"></lightning-button>
</footer>
</div>
</div>
<div class="slds-backdrop slds-backdrop_open"></div>
</template>
</template>
lwcModal.js
import { LightningElement, api, wire, track } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { CurrentPageReference } from 'lightning/navigation';
import { registerListener, unregisterAllListeners } from 'c/pubsub';
import getModalBody from '@salesforce/apex/lwcModalApex.getModalBody';
export default class LwcModal extends LightningElement {
@wire(CurrentPageReference) pageRef;
@api recordId;
@track loaded = false;
@track openModal = false;
@track error;
@track modalBody;
get modalClass(){
return this.openModal?'slds-modal slds-modal_large slds-fade-in-open':'slds-modal slds-modal_large';
}
handleLoad(){
getModalBody({rId : this.recordId})
.then(result => {
this.modalBody = result;
this.error = undefined;
this.loaded = true;
this.openModal = true;
})
.catch(error => {
this.error = error;
this.loaded = true;
this.showNotification('Error', error.body.message, 'error');
this.closeModal();
});
}
closeModal(){
this.openModal = false;
}
connectedCallback() {
registerListener('openModal', this.handleLoad, this);
}
disconnectedCallback() {
unregisterAllListeners(this);
}
showNotification(t,m,v) {
const evt = new ShowToastEvent({
title: t,
message: m,
variant: v
});
this.dispatchEvent(evt);
}
}
lwcModal.css
.slds-modal__content{
min-height: 15rem;
}
Apex Class
public class lwcModalApex {
@AuraEnabled(cacheable=true)
public static String getModalBody() {
return 'Modal body, Create anything as per the requirement, a huge complex wrapper may be :) ';
}
}
4. Finally and most importantly add the lwcModal component to the lightning page. remember pub/sub will only work b/w components on the same page, and this whole idea is to create a quick action which fires a publish event and closes itself the Lightning web Component which has subscribed for this event opens itself when it listens to the event published by the lightning component.
Thank you. This was a great help
ReplyDelete