2

So I've recently started jumping into LWC's more seriously, and I'm trying to figure it all out. I've created a custom picklist flow component which accepts a collection of strings as options (why this isn't standard I'll never know). I've managed to prevent moving onto the next page if the component is marked as "Required" using @api validate().

However, the issue is that if multiple of these components are on the same screen and a single one fails validation; then all of the components (even the valid ones) have their values cleared after showing a very brief loading icon. I'd like to mimic the standard required screen component/field functionality as close as possible to avoid input frustrations and inconsistencies.

Below is my current code:

component.js

import { LightningElement, api, track } from 'lwc';

export default class StringPicklistFlowComponent extends LightningElement {
    @api optionsArr;
    @api label;
    @api isRequired = false;
    @api value;

    get isNotRequired(){return !this.isRequired;}

    get options(){
        var arr = [];
        for(var i = 0; i < this.optionsArr.length; i++){
            var tmp = this.optionsArr[i].split(/,\s*/g);
            arr.push({label: tmp[0], value: tmp[1]});
        }
        return arr;
    }

    handleSelect(evt){
        this.value = evt.detail.value;
    }

    @api validate(){
        return {
            isValid: this.isNotRequired || this.value != null,
            errorMessage: "Please select an option"
        }
    }
}

component.html

<template>
    <label for="customPicklist" class="slds-form-element__label slds-rich-text-editor__output">
        <span class="slds-required" hidden={isNotRequired}>*</span>
        {label}
    </label>
    <lightning-combobox id="customPicklist" value={value} options={options} onchange={handleSelect}>
    </lightning-combobox>
</template>

Note that I did create a label manually. This is because the default functionality when the field was directly marked as "required" would constantly show a field error while the component value was null, which is a bit annoying.

Any help on this would be awesome, as this has been nagging at me for the better part of a day.

2 Answers2

2

I managed to find a solution, so I'll post it here in case anybody else comes across this issue. Basically, the problem boils down to the component getting re-rendered, and hence losing it's previous data. To get around this, you can use the native browser sessionStorage to store values, and then when re-rendered use the connectedCallback hook to set the component value. Here's what my code looks like now:

component.js

import { LightningElement, api, track } from 'lwc';

export default class StringPicklistFlowComponent extends LightningElement {
    @api isRequired = false;
    @api optionsArr;
    @api label;
    @api value;

    @api connectedCallback(){
        if(!!sessionStorage[this.storageTag])
            this.value = sessionStorage[this.storageTag];
        else
            sessionStorage[this.storageTag] = this.value;
    }

    get storageTag(){ return this.label + 'myTag5135'; }

    get isNotRequired(){ return !this.isRequired; }

    get options(){
        var arr = [];
        for(var i = 0; i < this.optionsArr.length; i++){
            var tmp = this.optionsArr[i].split(/,\s*/g);
            arr.push({label: tmp[0], value: tmp[1]});
        }
        return arr;
    }

    handleSelect(evt){
        this.value = evt.detail.value;
        sessionStorage[this.storageTag] = this.value;
    }

    @api validate(){
        return {
            isValid: this.isNotRequired || !!this.value,
            errorMessage: "Please select an option"
        };
    }
}

component.html

<template>
    <div>
        <label for="customPicklist" class="slds-form-element__label">
            <abbr class="slds-required" hidden={isNotRequired}>* </abbr>{label}
        </label>
        <lightning-combobox dropdown-alignment="auto" id="customPicklist" data-fieldname={label} variant="label-hidden" value={value} options={options} onchange={handleSelect}>
        </lightning-combobox>
    </div>
</template>

If you'll notice, I AM using the label property which isn't ideal (no enforcement that it's unique). I'd like to use the components api name in the flow so I can virtually guarantee uniqueness, however I've yet to find how to get this default property in the component. If anybody knows how, I'd really appreciate it. Anyways, I hope this helps anyone whose had similar frustrations with this wierd default limitation.

0

I would recommend using the FlowAttributeChangeEvent to update the flow attribute data. Refer to documentation to see how to use it.

Diaboloxx
  • 121
  • 1
  • 8