2

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

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 May 14 '20 at 17:07
  • Nevermind, I seem to have fixed the problem by setting fieldValue = "" at the start of the JS file – Jwok May 14 '20 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.