4

tl;dr - How does one get input validation to work for an LWC in the flow builder?

Background

I have created an LWC for text input that will alert the user when they are approaching or have exceeded the character limit for that field. I want the flow to prevent the user from going to the next flow page if the text entered into my component is greater than the passed character limit. My component is working fine, but I am having trouble getting the Flow to validate the data entered.

I have tried following the instructions on the Develop Components for Flow Screens section for adding a validation method, and have added a "validate" method to the javascript of the component. However, when I enter a value over the passed character limit and click "next" in the flow page, no error occurs.

One solution I found here suggests adding a "Next" button as part of the component, but I'd prefer to use the native flow "Next" button if possible. Can this be done, and if so, what is missing from my code?

Code

HTML

<template>
  <lightning-input
    name={field}
    label={fieldName}
    onchange={handleChange}
  ></lightning-input>
  <template if:true={isErrorMessage}>
    <span class="slds-text-color_error">{errorMessage}</span>
  </template>
</template>

JS

import { LightningElement, api } from "lwc";

export default class TextInputForFlow extends LightningElement {
  @api fieldName;
  @api characterLimit = 255;
  @api fieldValue;

  errorMessage = "";

  get errorMessageLength() {
    return this.errorMessage.length;
  }
  set errorMessageLength(event) {
    return this.errorMessage.length;
  }

  get isErrorMessage() {
    return this.errorMessageLength > 0;
  }
  set isErrorMessage(event) {
    return this.errorMessageLength > 0;
  }

  handleChange(event) {
    let length = event.target.value.length;
    // console.log(`length: ${length}`);
    if (length > this.characterLimit) {
      this.errorMessage = `Your answer must be less than 255 characters. Your character counts is ${length}`;
      this.validate();
    } else if (
      (length <= this.characterLimit) &
      (length > this.characterLimit - 25)
    ) {
      let left = this.characterLimit - length;
      this.errorMessage = `You have ${left} of ${this.characterLimit} characters remaining`;
      this.fieldValue = event.target.value;
      this.validate();
    } else {
      this.errorMessage = "";
      this.fieldValue = event.target.value;
      this.validate();
    }
  }

  @api
  validate() {
    if (this.fieldValue.length <= this.characterLimit) {
      return { isValid: true };
    }
    return {
      isValid: false,
      errorMessage: "/*Your answer must be less than 255 characters*/"
    };
  }
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>True</isExposed>
    <targets>
        <target>lightning__FlowScreen</target>
        <target>lightning__HomePage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__FlowScreen, lightning__HomePage">
            <property name="fieldName" label="Field Name" type="String" />
            <property name="characterLimit" label="Character Limit" type="Integer" />
            <property name="fieldValue" label="Field Value" type="String" />
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

3 Answers 3

3

You will also need to dispatch the FlowAttributeChangeEvent telling flow the attribute value has changed like this

 handleChange(event) {
    let length = event.target.value.length;
    const attributeChangeEvent = new FlowAttributeChangeEvent('fieldValue', event.target.value);
        this.dispatchEvent(attributeChangeEvent);  


    // console.log(`length: ${length}`);
    if (length > this.characterLimit) {
      this.errorMessage = `Your answer must be less than 255 characters. Your character counts is ${length}`;

    } else if (
      (length <= this.characterLimit) &
      (length > this.characterLimit - 25)
    ) {
      let left = this.characterLimit - length;
      this.errorMessage = `You have ${left} of ${this.characterLimit} characters remaining`;
      this.fieldValue = event.target.value;

    } else {
      this.errorMessage = "";
      this.fieldValue = event.target.value;

    }
  }
2
  • Thanks so much. This code is working, with one strange exception. If I click "next" on the flow without having entered any data into the lwc-field, the button does not respond and remains unresponsive even after entering data. Do you have any idea as to what might be causing this?
    – Jwok
    Commented May 14, 2020 at 17:07
  • Nevermind, I seem to have fixed the problem by setting fieldValue = "" at the start of the JS file
    – Jwok
    Commented May 14, 2020 at 17:22
1

For any future readers, the final code for this project was as follows:

HTML

<template>
  <lightning-input
    name={field}
    label={fieldName}
    onchange={handleChange}
  ></lightning-input>
  <template if:true={isErrorMessage}>
    <span class="slds-text-color_error">{errorMessage}</span>
  </template>
</template>

JS

import { LightningElement, api } from "lwc";
import { FlowAttributeChangeEvent } from "lightning/flowSupport";

export default class TextInputForFlow extends LightningElement {
  @api fieldName;
  @api characterLimit = 255;
  @api fieldValue = "";

  errorMessage = "";

  renderedCallback(){
    this.validate();
  }

  get errorMessageLength() {
    return this.errorMessage.length;
  }
  set errorMessageLength(event) {
    return this.errorMessage.length;
  }

  get isErrorMessage() {
    return this.errorMessageLength > 0;
  }
  set isErrorMessage(event) {
    return this.errorMessageLength > 0;
  }

  handleChange(event) {
    let length = event.target.value.length;

    const attributeChangeEvent = new FlowAttributeChangeEvent(
      "fieldValue",
      event.target.value
    );

    this.dispatchEvent(attributeChangeEvent);

    if (length > this.characterLimit) {
      this.errorMessage = `Your answer must be less than 255 characters. Your character counts is ${length}`;
    } else if (
      (length <= this.characterLimit) &
      (length > this.characterLimit - 25)
    ) {
      let left = this.characterLimit - length;
      this.errorMessage = `You have ${left} of ${this.characterLimit} characters remaining`;
      this.fieldValue = event.target.value;
    } else {
      this.errorMessage = "";
      this.fieldValue = event.target.value;
    }

  }

  @api
  validate() {
    let length = this.fieldValue.length;
    console.log(`length: ${length}`);
    if ((length <= this.characterLimit) & (length > 0)) {
      return { isValid: true };
    } else if (length === 0 || this.fieldValue === null) {
      return {
        isValid: false,
        errorMessage: "This field is required"
      };
    }
    return {
      isValid: false,
      errorMessage: "Your answer must be less than 255 characters"
    };
  }
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>True</isExposed>
    <targets>
        <target>lightning__FlowScreen</target>
        <target>lightning__HomePage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__FlowScreen, lightning__HomePage">
            <property name="fieldName" label="Field Name" type="String" />
            <property name="characterLimit" label="Character Limit" type="Integer" />
            <property name="fieldValue" label="Field Value" type="String" />
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

The only issue I am now facing is that if an end-user selects "next" while there are more than the allotted characters allowed in the field, the field value resets to blank when the screen reloads and the error message is displayed. I will likely post this as a new question if I cannot resolve it internally.

4
  • Were you able to find solution for the screen reload? Commented May 10, 2022 at 20:57
  • @VinodAgrawal unfortunately I'm no longer at the job where I did this work so I can't review the flow in question. I'd recommend you create a new question for your issue
    – Jwok
    Commented May 11, 2022 at 23:42
  • How did you wire up the validate to the flow?
    – user8560
    Commented Jul 6, 2023 at 23:41
  • @user8560 I don't remember at this point and I'm no longer at the job where I did this work so I can't review it. I'd recommend posting a new question.
    – Jwok
    Commented Jul 12, 2023 at 2:02
0

One more detail for future readers is that, don't forget to define an error message string to the errorMessage that you are throwing from the validate(). Defining it simply as below: @api errorMessage; would result in the flow skipping showing the error message even if the validate method is called.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .