iI have faced issue with screen flow and LWC as screen component here is component code:
import { LightningElement, wire } from 'lwc';
import {APPLICATION_SCOPE, MessageContext, publish, subscribe, unsubscribe} from "lightning/messageService";
import sampleMessageChannel from '@salesforce/messageChannel/SampleMessageChannel__c';
import crossFormValidationChannel from '@salesforce/messageChannel/CrossFormValidation__c';
export default class SelectServiceLevelProcessor extends LightningElement {
subscription = null;
second_sub = null;
@wire(MessageContext)
messageContext;
connectedCallback() {
this.subscribeToMessageChannel();
//publish(this.messageContext, sampleMessageChannel, { action: 'selectServiceLevel'});
}
disconnectedCallback() {
this.unsubscribeToMessageChannel();
}
subscribeToMessageChannel() {
console.log("serviceProcessor");
console.log(JSON.stringify(this.messageContext));
try {
if (!this.subscription) {
this.subscription = subscribe(
this.messageContext,
sampleMessageChannel,
(message) => this.handleMessage(message),
{scope: APPLICATION_SCOPE}
);
}
} catch (error) {
console.log('subscribeToMessageChannel error: ' + JSON.stringify(error));
}
console.log("serviceProcessor1");
console.log(JSON.stringify(this.messageContext));
try {
if (!this.subscription) {
this.subscription = subscribe(
this.messageContext,
crossFormValidationChannel,
(message) => this.handleMessage(message),
{scope: APPLICATION_SCOPE}
);
}
} catch (error) {
console.log('subscribeToMessageChannel error: ' + JSON.stringify(error));
}
}
unsubscribeToMessageChannel() {
unsubscribe(this.subscription);
this.subscription = null;
}
handleMessage(message) {
alert('test');
console.log('message:::' + JSON.stringify(message));
}
}
import { LightningElement, wire } from 'lwc';
import {APPLICATION_SCOPE, MessageContext, publish, subscribe, unsubscribe} from "lightning/messageService";
import sampleMessageChannel from '@salesforce/messageChannel/SampleMessageChannel__c';
import crossFormValidationChannel from '@salesforce/messageChannel/CrossFormValidation__c';
export default class SelectServiceLevelProcessor extends LightningElement {
subscription = null;
second_sub = null;
@wire(MessageContext)
messageContext;
connectedCallback() {
this.subscribeToMessageChannel();
//publish(this.messageContext, sampleMessageChannel, { action: 'selectServiceLevel'});
}
disconnectedCallback() {
this.unsubscribeToMessageChannel();
}
subscribeToMessageChannel() {
console.log("serviceProcessor");
console.log(JSON.stringify(this.messageContext));
try {
if (!this.subscription) {
this.subscription = subscribe(
this.messageContext,
sampleMessageChannel,
(message) => this.handleMessage(message),
{scope: APPLICATION_SCOPE}
);
}
} catch (error) {
console.log('subscribeToMessageChannel error: ' + JSON.stringify(error));
}
console.log("serviceProcessor1");
console.log(JSON.stringify(this.messageContext));
try {
if (!this.subscription) {
this.subscription = subscribe(
this.messageContext,
crossFormValidationChannel,
(message) => this.handleMessage(message),
{scope: APPLICATION_SCOPE}
);
}
} catch (error) {
console.log('subscribeToMessageChannel error: ' + JSON.stringify(error));
}
}
unsubscribeToMessageChannel() {
unsubscribe(this.subscription);
this.subscription = null;
}
handleMessage(message) {
alert('test');
console.log('message:::' + JSON.stringify(message));
}
}
And xmlXML:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>57.0</apiVersion>
<isExposed>true</isExposed>
<description>Select Service Level</description>
<isExposed>true</isExposed>
<masterLabel>Select Service Levels Processor</masterLabel>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__FlowScreen</target>
<target>lightningCommunity__Page</target>
<target>lightningCommunity__Default</target>
</targets>
</LightningComponentBundle>
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>57.0</apiVersion>
<isExposed>true</isExposed>
<description>Select Service Level</description>
<isExposed>true</isExposed>
<masterLabel>Select Service Levels Processor</masterLabel>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__FlowScreen</target>
<target>lightningCommunity__Page</target>
<target>lightningCommunity__Default</target>
</targets>
</LightningComponentBundle>
It subscribing to message channel and publish test allert, but if we will place it into screen flow as screen component it did not subscribing
screen has another component with subscribing which works well(subscribe to LMS) but new one not...
iI have tried different API versions of LWC (51/54/57) most of component on 54v but it doesn't affect
import {LightningElement, api, wire, track} from 'lwc'; import { FlowAttributeChangeEvent, FlowNavigationNextEvent, FlowNavigationBackEvent, FlowNavigationFinishEvent } from 'lightning/flowSupport';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import {APPLICATION_SCOPE, MessageContext, publish, subscribe, unsubscribe} from "lightning/messageService"; import crossFormValidationChannel from '@salesforce/messageChannel/CrossFormValidation__c';
export default class OnboardingProgressFooter extends LightningElement {
@api availableActions = [];
@api steps = ['Step 1', 'Step 2'];
@api completed_steps = [];
@api current_step = '1';
showNext = false;
showPrevious = false;
showFinish = false;
step_objects = [];
forms_to_validate = [
'orderDetails',
'pickup_validated',
'delivery_validated'
]
forms_valid_arr = [
false,
false,
false
]
get forms_valid(){
return this.forms_valid_arr;
}
set forms_valid(value){
if(value.every(element => element === true)){
if (this.availableActions.find((action) => action === 'NEXT')) {
const navigateNextEvent = new FlowNavigationNextEvent();
this.dispatchEvent(navigateNextEvent);
}
}
if(value != this.forms_valid_arr){
this.forms_valid_arr = value;
}
}
@wire(MessageContext)
messageContext;
connectedCallback() {
this.subscribeToMessageChannel();
console.log('available actions: ');
console.log(this.availableActions);
this.showNext = !!(this.availableActions.find((action) => action === 'NEXT'));
this.showPrevious = !!(this.availableActions.find((action) => action === 'BACK'));
this.showFinish = !!(this.availableActions.find((action) => action === 'FINISH'));
this.createStepObjects();
console.log(this.showPrevious);
}
disconnectedCallback() {
this.unsubscribeToMessageChannel();
}
subscribeToMessageChannel() {
if (!this.subscription) {
this.subscription = subscribe(
this.messageContext,
crossFormValidationChannel,
(message) => this.handleMessage(message),
{scope: APPLICATION_SCOPE}
);
}
}
handleMessage(message){
console.log('MESSAGE RECEIVED IN FOOTER');
console.log(message);
if(message.action === 'form_submitted'){
if(message.data === 'orderDetail'){
this.forms_valid_arr[0] = true;
}else if(message.data === 'pickup_validated'){
this.forms_valid_arr[1] = true;
}else if(message.data === 'delivery_validated'){
this.forms_valid_arr[2] = true;
}else if(message.data === 'service_level_selected'){
this.forms_valid_arr = [];
this.forms_valid_arr[0] = true;
}
this.forms_valid = [...this.forms_valid_arr];
}
}
unsubscribeToMessageChannel() {
unsubscribe(this.subscription);
this.subscription = null;
}
handleGoPrevious(evt){
evt.preventDefault();
// check if NEXT is allowed on this screen
if (this.availableActions.find((action) => action === 'BACK')) {
// navigate to the next screen
const navigateBackEvent = new FlowNavigationBackEvent();
this.dispatchEvent(navigateBackEvent);
}
}
handleFinish(evt){
evt.preventDefault();
// check if NEXT is allowed on this screen
if (this.availableActions.find((action) => action === 'FINISH')) {
// navigate to the next screen
const handleFinishEvent = new FlowNavigationFinishEvent();
this.dispatchEvent(handleFinishEvent);
}
}
handleGoNext(evt) {
evt.preventDefault();
publish(this.messageContext, crossFormValidationChannel, { action: 'submit'});
}
createStepObjects(){
console.log('creating step objects');
this.steps.forEach(step => {
console.log(step);
this.step_objects.push({
label : step,
value : this.step_objects.length + 1,
is_complete : this.getIsCompletedStep(step)
});
});
}
getIsCompletedStep(step){
return false;
}
}
import {LightningElement, api, wire, track} from 'lwc';
import {
FlowAttributeChangeEvent,
FlowNavigationNextEvent,
FlowNavigationBackEvent,
FlowNavigationFinishEvent
} from 'lightning/flowSupport';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import {APPLICATION_SCOPE, MessageContext, publish, subscribe, unsubscribe} from "lightning/messageService";
import crossFormValidationChannel from '@salesforce/messageChannel/CrossFormValidation__c';
export default class OnboardingProgressFooter extends LightningElement {
@api availableActions = [];
@api steps = ['Step 1', 'Step 2'];
@api completed_steps = [];
@api current_step = '1';
showNext = false;
showPrevious = false;
showFinish = false;
step_objects = [];
forms_to_validate = [
'orderDetails',
'pickup_validated',
'delivery_validated'
]
forms_valid_arr = [
false,
false,
false
]
get forms_valid(){
return this.forms_valid_arr;
}
set forms_valid(value){
if(value.every(element => element === true)){
if (this.availableActions.find((action) => action === 'NEXT')) {
const navigateNextEvent = new FlowNavigationNextEvent();
this.dispatchEvent(navigateNextEvent);
}
}
if(value != this.forms_valid_arr){
this.forms_valid_arr = value;
}
}
@wire(MessageContext)
messageContext;
connectedCallback() {
this.subscribeToMessageChannel();
console.log('available actions: ');
console.log(this.availableActions);
this.showNext = !!(this.availableActions.find((action) => action === 'NEXT'));
this.showPrevious = !!(this.availableActions.find((action) => action === 'BACK'));
this.showFinish = !!(this.availableActions.find((action) => action === 'FINISH'));
this.createStepObjects();
console.log(this.showPrevious);
}
disconnectedCallback() {
this.unsubscribeToMessageChannel();
}
subscribeToMessageChannel() {
if (!this.subscription) {
this.subscription = subscribe(
this.messageContext,
crossFormValidationChannel,
(message) => this.handleMessage(message),
{scope: APPLICATION_SCOPE}
);
}
}
handleMessage(message){
console.log('MESSAGE RECEIVED IN FOOTER');
console.log(message);
if(message.action === 'form_submitted'){
if(message.data === 'orderDetail'){
this.forms_valid_arr[0] = true;
}else if(message.data === 'pickup_validated'){
this.forms_valid_arr[1] = true;
}else if(message.data === 'delivery_validated'){
this.forms_valid_arr[2] = true;
}else if(message.data === 'service_level_selected'){
this.forms_valid_arr = [];
this.forms_valid_arr[0] = true;
}
this.forms_valid = [...this.forms_valid_arr];
}
}
unsubscribeToMessageChannel() {
unsubscribe(this.subscription);
this.subscription = null;
}
handleGoPrevious(evt){
evt.preventDefault();
// check if NEXT is allowed on this screen
if (this.availableActions.find((action) => action === 'BACK')) {
// navigate to the next screen
const navigateBackEvent = new FlowNavigationBackEvent();
this.dispatchEvent(navigateBackEvent);
}
}
handleFinish(evt){
evt.preventDefault();
// check if NEXT is allowed on this screen
if (this.availableActions.find((action) => action === 'FINISH')) {
// navigate to the next screen
const handleFinishEvent = new FlowNavigationFinishEvent();
this.dispatchEvent(handleFinishEvent);
}
}
handleGoNext(evt) {
evt.preventDefault();
publish(this.messageContext, crossFormValidationChannel, { action: 'submit'});
}
createStepObjects(){
console.log('creating step objects');
this.steps.forEach(step => {
console.log(step);
this.step_objects.push({
label : step,
value : this.step_objects.length + 1,
is_complete : this.getIsCompletedStep(step)
});
});
}
getIsCompletedStep(step){
return false;
}
}
and xmlXML:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>54.0</apiVersion>
<description>Onboarding Progress Footer</description>
<isExposed>true</isExposed>
<masterLabel>Onboarding Progress Footer</masterLabel>
<targets>
<target>lightning__FlowScreen</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__FlowScreen">
<property name="steps" type="String[]" />
<property name="completed_steps" type="Boolean[]" />
<property name="current_step" type="String" />
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>54.0</apiVersion>
<description>Onboarding Progress Footer</description>
<isExposed>true</isExposed>
<masterLabel>Onboarding Progress Footer</masterLabel>
<targets>
<target>lightning__FlowScreen</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__FlowScreen">
<property name="steps" type="String[]" />
<property name="completed_steps" type="Boolean[]" />
<property name="current_step" type="String" />
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
So as iI mentioned second component subs well, in screen flow nothing special, screen, first and second conponent, second with entered properties and all, but first one did not response