Dec 25th, 2021: [en] Using Elastic to build forms in your app

While Elastic is most known for our open-source search tools, did you know we also have an open-source design library that anyone can use for creating the user interface inside of your apps and websites? You can not only handle your data with Elastic, but you can also display and interact with the data with Elastic too!

It’s all thanks to our design library called EUI (Elastic User Interface). You might recognize some of the components (no pun intended) from Kibana. For today’s post, I want to share one of my favorite EUI Component - The Form - and how you can use it in your app.

Set up EUI

Getting started with EUI in your React app is simple. For the most part, you just need to add @elastic/eui as a dependency in your project and import the CSS files. Then you’re ready to start using the components!

Out of the Box Form

Just about every app needs to collect input from a user and EUI provides a lot of options for doing just that. The styling comes out of the box but allows for customization. (As a bonus, you can apply classNames to every EUI component to apply your own custom styles.)

We use the form component in our customer support portal for users to create a new support case.

As you can see, you can use just about anything as an input type! We have some really advanced dropdowns here, a file picker, a text input, and even a markdown editor!

Here’s an example of how we format a field for adding contacts to a case:

<EuiFormRow
  fullWidth // this defines the width
  label={
    <EuiI18n
      token="newCase.informed"
      default="Who else should we keep informed? (optional)"
    />
  } // label for the row, with options for localizing text through our i18n utility
>
  <EuiI18n
    token="newCase.informedPlaceholder"
    default="Select contacts"
  > // default text over the box
    {(informedPlaceholder: string) => (
      <EuiComboBox // dropdown input type
        fullWidth 
        isClearable={true} // customization option allowing you to define the ability to remove all the selections
        isLoading={
          this.props.contacts.loading ? true : undefined
        } // define a loading state
        onChange={this.handleContactSelect} // what it sounds like :) 
        options={this.state.contactOptions} // an array containing all the dropdown values 
        placeholder={informedPlaceholder} // default text
        selectedOptions={this.state.contactsSelected} // which values are selected
      />
    )}
  </EuiI18n>
</EuiFormRow>

You can read more about these props in the EUI Docs.

Incorporating Validation

If you want to ensure only the right data comes through the field, you'll be able to easily set up form validation and error handling with EUI.

You'll need to add two props to a form row to set it, and then you'll need to create an onChange event for the field and/or an onSubmit event for the form to check the criteria of the values.

  1. Define isInvalid. You'll need to add a prop to your field that accepts a boolean for showing if the field is valid or not. This will change the color of the field's box to red so that a user can visibly see the field needs edits. This is the field we will set in the onSubmit function in a few steps.
isInvalid={this.state.formErrors.statusEmpty}
  1. Pass an array of messages to show error. This could be just one error (like "cannot be blank"), or if you have multiple types of errors that can occur, you can pass each of those in there with the criteria.)
error={[
// we're passing two errors - one that checks if the field is empty 
// and another to check if it's too long
  this.state.formErrors.bodyTooLong && (
    <EuiI18n
      token="newCase.lengthErrorMessage"
      default="Must be less than {maxLength} characters."
      values={{
        maxLength: MAX_BODY_LENGTH,
      }}
    />
  ),
  this.state.formErrors.bodyEmpty && (
    <EuiI18n
      token="newCase.bodyEmptyErrorMessage"
      default="The description cannot be empty."
    />
  ),
 ]}
  1. Create a handler function to check your criteria on form submission and update your isInvalid/error fields.
if (
  !body ||
  !subject
  ) {
  this.setState((prevState) => {
    return {
      formErrors: {
        ...prevState.formErrors,
        bodyEmpty: !body,
        subjectEmpty: !subject,
      },
    };
});

And voila! Now you have error handling!
error-handling

Note - you can also create an onChange or onBlur event on those inputs to check before the form is submitted.

I've only scratched the surface here. To learn more, check out the EUI Forms docs and see all the different ways you can customize them and use them!

4 Likes

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.