Developers / Platform

Leverage Salesforce Lightning-Input for Superior User Interactions

By Alex Crisp

Of all the base Lightning components, there’s easily a standout winner in the “what gets used the most” competition, and that is the lightning-input (or lightning:input when in Aura) component. 

However, despite its widespread use, there are still many aspects of this component that developers may not be fully aware of. So let’s take a dive into what this component does, and look at some tips and tricks to get the most out of it.

Component Attributes

As with all Lightning components, one of the key ways we utilise it is through its attributes, allowing us to tweak and change the component to serve our needs better. However, due to the wide range of different types of input that lightning-input can handle, there are a vast number of attributes available, and not all of them will be relevant to the specific use case at hand. Despite this, there are a few key attributes which are shared across most, if not all, of the different input types.

  • label: The descriptive text that appears alongside the actual input, useful for providing a descriptive caption about the input’s purpose. This attribute is always required.
  • type: Alters the look and behaviour of the input: for example a date input or a text input. We’ll look at these in more detail below.
  • name: A unique identifier for the input, useful when handling the component programmatically.
  • value: The current value of the component, which allows us to set its value within our HTML template and bind it to our component’s JavaScript controller class.
  • disabled: Prevents users from interacting with the input, and changes the visual appearance of the input to indicate its disabled status.
  • read-only: Similar to the disabled state, however with a different visual appearance, usually used to indicate input data is relevant but not editable.
  • required: Indicates that an input must be completed for submission and visually modifies the input to indicate so.
  • variant: Alters how the input looks based on one of the variants:
    • standard: The default look and feel.
    • label-inline: Horizontally aligns the input and label.
    • label-stacked: Places the label above the input.
    • label-hidden: Hides the label, but still allows it to be read by assistive technologies such as screen readers
  • aria-X: The Accessible Rich Internet Applications (ARIA) attributes are special attributes that are used to provide additional context to components to assist in accessibility.

By leveraging these attributes, you can very easily and rapidly create forms with a nice, consistent, and user-friendly interface, but the real power comes when we start utilizing the different types and attributes associated with them.

READ MORE: Your Guide to Lightning Web Components: Let’s Explore LWC

Different Types and Their Attributes

It’s important to remember that different types have different attributes, and we’ll go over some of them now.

  • checkbox: A simple checkbox showing a checked or unchecked state. Unlike most other types, its value is controlled via the checked attribute and not the value attribute.
    • styling hooks: We can control the color of the checkbox background and the tick using these two styling hooks respectively:
      • –sds-c-checkbox-color-background-checked.
      • –sds-c-checkbox-mark-color-foreground.
  • checkbox-button: Similar to a checkbox, however it is visually different. Instead of having a checkbox, it is shown as a button with two visual distinct states – useful when you need simple toggle states within a UI. As with the checkbox, it also uses checked attributes instead of value.
  • color: Provides an interface for a user to view and choose a color using a simple color picker interface, or by providing their own RGB/Hex values instead.
  • date: Allows a user to enter a date (e.g. 1/1/2023), or to select one through the use of a date picker. This type has several attributes to further configure it.
    • date-style: How the date will look after being selected. These can be short, medium or long and the specific of how these look is based upon the user’s locale.
    • min: Allows a minimum date to be selected, with an error being shown if a date is selected before this date.
  • max: Allows a maximum date to be selected, with an error being shown if a date is selected past this date.
  • datetime: Provides both a date picker and a time picker, with both being required for a valid value to be output. This type uses the same attributes for customization as the date and time types.
  • email: a simple text input, which shows an error if the inputted format isn’t email like: “email@address”.
    • min-length: Used to specify a minimum number of characters required.
    • max-length: Used to specify a minimum number of characters required.
  • file: Provides a button and a drop zone for a user to be able to select files on their local computer for consumption within the component (e.g. uploading to Salesforce). When clicking to upload files, the native file selector is shown. This type only provides an interface for selecting files and requires you to implement the actual file uploading. If you are uploading directly against a record, consider lightning-file-upload instead. There are several attributes to customize and work with the component:
    • files: After selecting the files, the chosen files are accessible via this attribute.
    • accept: Specify the file types which will be accepted and shown in the native file selector.
  • multiple: A Boolean attribute to indicate that a user may select multiple files. When this is false, the native file picker should only allow a single file to be selected.
  • number: A simple input for providing a number, with a few different attributes for behavior.
    • step: Configures the different increments that are made when a user presses their up or down arrow keys, incrementing or decrementing the value by that amount each time. Also defines the granularity of the values, e.g. selecting 1 for step will only allow whole integers, and 5 would allow multiples of 5.
    • min: Allows a minimum number to be selected, with an error being shown if a number imputed is lower than this.
    • max: Allows a minimum number to be selected, with an error being shown if a number imputed is higher than this.
    • formatter: Changes how the value is displayed; one of the following can be used:
      • decimal
      • percent: A 0-1 based percentage value.
      • percent-fixed: A 0-100 based percentage value.
      • currency: Uses the org’s currency for formatting.
  • password: A text input in which the displayed input is masked.
    • min-length: Used to specify a minimum number of characters required.
    • max-length: Used to specify a minimum number of characters required.
  • range: A slider which allows a user to select a value between to distinct numbers, supports the following attributes for customization:
    • step: Configures the different increments that are made when a user drags the slider.
    • min: Allows a minimum number to be selected, with an error being shown if a number imputed is lower than this.
    • max: Allows a minimum number to be selected, with an error being shown if a number imputed is higher than this.
  • search: A text input, which displays a search icon, indicating to a user the purpose of the field, can be toggled into a loading state to show a search is occurring.
    • is-loading: A Boolean which indicates whether the loading spinner should be displayed.
    • min-length: Used to specify a minimum number of characters required.
    • max-length: Used to specify a minimum number of characters required.
  • tel: A text input for a user provides a telephone number. The exact format needs providing via regex in the pattern attribute:
    • pattern: A regex pattern which the user input will be validated against, if the the value doesn’t match, an error will be displayed.
    • min-length: Used to specify a minimum number of characters required.
    • max-length: Used to specify a minimum number of characters required.
  • text: A basic text input without any special functionality.
    • min-length:  Used to specify a minimum number of characters required.
    • max-length: Used to specify a minimum number of characters required.
  • time: Provides an input for capturing a time value from a user. It provides a dropdown of selectable dates which are in 15 minute increments. Can be customized with the following attributes:
    • time-style: How the time will look after being selected. These can be short, medium or long and the specific of how these look is based upon the user’s locale.
    • min: Allows a minimum time to be selected, with an error being shown if a date is selected before this time.
    • max: Allows a maximum time to be selected, with an error being shown if a date is selected past this time.
  • toggle: An alternative to the checkbox and checkbox-button which more clearly and visually indicates the state of the button, useful when building UIs which are for toggling features or functionality on and off. Like the checkbox and checkbox-button types, this type also uses checked instead of value for its state. It can be customized with the following attributes:
    • message-toggle-active: Changes the text which is displayed under the toggle when it is checked.
    • message-toggle-inactive: Changes the text which is displayed under the toggle when it is unchecked.
    • styling hooks: We can customize the look of the color of the toggle switch and the background using these styling hooks respectively:
      • –sds-c-checkbox-toggle-switch-color-background
      • –sds-c-checkbox-toggle-color-background-checked
  • URL: A simple text input which validates that the conforms to a URL structure, with protocol, e.g. “http://”, “https://” etc.
READ MORE: Lightning Web Component Enhancements

User Interaction

Now that we know the different types of inputs we can use, we can build a pretty complex form with lots of different ways for a user to provide the required information. However, it’s not uncommon for us to need to perform background tasks, such as validation, Apex calls, or toggling other fields to be visible within the form.

To achieve this, we need our inputs to communicate that their value has changed, and just like any other LWC, we achieve this through the use of events. All of these inputs fire a change event whenever the value changes. We can then handle this event and get the value from the details object on the event from either the value, checked or files key, depending on the input type.

For components which allow the user to enter values using their keyboard, a change event will be fired for every keypress. If we are wishing to perform actions based on the value that was inputted, besides simply storing the value, it’s very likely that constantly performing these actions on every keystroke will lead to a very poor user experience. For example, if we are performing an Apex action, every keystroke will trigger a new network call, and potentially the majority of them will not be required as the user continues to type.

READ MORE: Lightning Web Component Communication Using Events

Alternatively, we could switch to using the blur event, which will only fire when a user clicks out of the input, however this is also quite a poor experience and can be quite confusing. Instead we want to use a technique called debouncing.

Debouncing

Debouncing is the technique of filtering a function call based on repeated requests. In our input, the function call would be our event handler (or more specifically, the action we wish to perform). To do this, we need to firstly capture any of the fired events, and then cancel or delay actually performing our expensive logic. Thankfully, JavaScript provides everything we need to do this quite easily by following these simple steps:

  • Have a property within our component’s class which we can use to store a timeout.
  • In our event handler, clear the value in property we made in step 1 using clearTimeout().
  • Create a new timeout using setTimeout() and assign its returned value to the property from step 1.
  • Write our logic within the timeout.

In essence, what this code does is schedule a piece of code to run at a later time. If we have another call to the same function, we cancel the previous scheduled piece of code and reschedule it. This allows us to only execute our code when the user has stopped typing, and the input is likely to be valid. 

We need to be careful with the timeout value we chose, as choosing one which is too quick won’t provide enough time for someone’s fingers to move between keys and won’t actually offer any benefit. Choosing one which is too slow will cause a noticeable lag between a user stopping typing and the action occurring which creates the perception that the code is slow, even if it isn’t. 

Ideally, never go faster than 300ms and slower than 600ms, with the faster end being used for very fast executing code and the longer end for code which involves expensive operations or network calls, as these are actions we ideally only want to perform when required.

Custom Validation

Validation is a hugely important part of building any user interface, ensuring that we capture only correct data, and feeding that back to the user is an essential part of that process. To do this, we can use some of the attributes of lightning-input, as well as some of the component methods, which can allow us to enforce specific input criteria and provide meaningful error messaging, ensuring everyone fully understands why an input may not be valid.

To achieve this we can use the “message-when-x” attributes:

  • message-when-bad-input: Generic message for when the imputed value is bad.
  • message-when-pattern-mismatch: Displayed when a regex pattern has been provided, but the user’s input doesn’t match that pattern
  • message-when-range-overflow: A minimum value has been provided and the user’s inputted value is below this, e.g. on number or date fields.
  • message-when-range-underflow: A maximum value has been provided and the user’s inputted value is above this, e.g. on number or date fields.
  • message-when-step-mismatch: On a number field, a step has been defined and the user’s input value doesn’t match it: e.g. with a step of 5 and a value of 4.
  • message-when-too-long: When the inputted text is longer than the limit defined in max-length.
  • message-when-too-short: When the inputted text is shorter than the limit defined in min-length.
  • message-when-type-mismatch: When the user has put in an incorrect data type for a field, for example putting text into a date field.
  • message-when-value-missing: The error displayed when no value has been provided and the field is set as required.

There also comes a time when simply using the provided validation attributes and their messages simply doesn’t cut it, and you need to do some custom logic for validation and then reflect that back to the field with an appropriate message. We can do this using our change handler to calculate our validity state and then reflecting it back to the input using setCustomValidity() method. #

By utilizing this method, we can flag a component as invalid and provide a specific message about why, ensuring a good user experience. We can also use this method to set a component as valid by removing any existing error message. After setting the error message, we then call the reportValidity() method to have the input display that to the user.

Summary

The lightning-input component is a powerful tool for creating user-friendly forms or interfaces within Salesforce. By leveraging its capabilities, such as the different types and attributes, developers can tailor it to suit almost any use case. 

However, it is crucial for developers to recognize their responsibility in ensuring that these inputs meet user expectations, provide timely feedback, and maintain optimal performance. Techniques like debouncing and custom error messaging, which are often overlooked, play a vital role in achieving this goal. By implementing these techniques, developers can enhance user interaction, and take them to the next level.

Don’t forget, one of the most important things when building user facing interfaces is to prioritize the user’s interactions and ensuring they have as smooth and frustration free experience as possible.

The Author

Alex Crisp

Alex is CTO for Seven20, an ISV providing a CRM/ATS built on Salesforce. He has a wealth of experience building everything and anything on the Salesforce platform.

Leave a Reply to Dewayne Cancel reply

Comments:

    Dewayne
    July 14, 2023 4:35 am
    I still find it confusing as to the difference between lightning-input and lightning-input-field and when to use one over the other. It seems like I have more flexibility as to what I can do with lightning-input so is there any need to even use lightning-input-field? Your insights would be appreciated.