C3 AI Documentation Home

Create custom inputs for forms and filter panels

This document will lead you through instructions on how to custom inputs for both UiSdlForm and UiSdlFilterPanel.

Making a custom input for forms

Define the c3typ files

First, you will need to create a c3typ file for your input. This will define the props the actual input component will take in and must mix UiSdlCustomInputBase and UiSdlComponent. In this example, you will make a text input like so:

Type
type CustomTextField mixes UiSdlCustomInputBase, UiSdlComponent<UiSdlNoData> {
  /**
   * Text to display when no value has been added yet.
   */
  placeholder: string
}

Here, it will only take a placeholder as a prop.

Second, you will need to define the c3typ file for the React implementation of the input. This type will mix the previous type and ReactFunction. Optionally, it can also mix UiSdlInputReact to add the UiSdlInputReact#shouldRenderAsConnectedDynamicComponent function. This function allows your component to be rendered as a dynamic component with its own id and redux state if needed.

Type
type CustomTextFieldReact mixes CustomTextField, ReactFunction, UiSdlInputReact {
  render: ~ tsx-client
}

Create the component React file

Once you have your c3typs, you can now create the React implementation of your custom input.

JavaScript
import * as React from 'react';
import SDLFormGroup from '@c3/sdl-react/reactComponents/SDLFormGroup';

const CustomTextField = (props) => {
  const handleChange = (e) => {
    props.onChange(e, { field: props.field, value: e.target.value, state: { value: e.target.value } });
  };
  return (
    <SDLFormGroup {...props}>
      <input type="text" placeholder={props.placeholder} onChange={handleChange} />
    </SDLFormGroup>
  );
};

const shouldRenderAsConnectedDynamicComponent = (props) => {
  return false;
};

export { shouldRenderAsConnectedDynamicComponent };
export default CustomTextField;

In this example, the input tag is the actual custom input, just a text input here. In order to handle extra form features such as labels, hint text, and required css, it is wrapped in a SDLFormGroup. This allows for a C3 look and feel for those features without custom css. The form will pass down an onChange function into the input in order to update the UiSdlForm#formFieldValues in redux when the input's value changes.

Additionally, this example has an implementation of UiSdlInputReact#shouldRenderAsConnectedDynamicComponent, which just returns false here since this component never needs to be rendered dynamically.

Create the component instance

Once the input is complete, it can be added to a form json file. To simplify the example, this form will only have one input like so:

JSON
{
  "type": "UiSdlConnected<UiSdlForm>",
  "component": {
    "dataSpec": {
      "fieldSets": {
        "type": "[UiSdlFormFieldSet]",
        "value": [
          {
            "type": "UiSdlFormFieldSet",
            "fields": [
              {
                "inputElement": {
                  "type": "CustomTextField",
                  "placeholder": "Placeholder"
                },
                "label": "Name",
                "required": true,
                "fieldName": "name"
              }
            ]
          }
        ]
      }
    }
  }
}

Making a custom input for filter panels

After making an input that can be used in a form, there is an extra step to make sure that the input can be used for filter panels.

Define the c3typ file

When adding an input for use in a filter panel, it needs to have a type that mixes UiSdlFieldSetFilterField. UiSdlFieldSetFilterField takes in the input's type in the c3typ definition, so if a filter field that uses CustomTextField can be defined like so:

Type
type CustomTextFieldFilterField mixes UiSdlFieldSetFilterField<CustomTextField> {
  operator: ~ = 'EQUALS'
}

Here, CustomTextField is passed into the <> to specify that it is the input element to be used, and the operator field is added to specify how the filter should be constructed from the value of the input.

Create the component instance

You can then use your new CustomTextFieldFilterField in a UiSdlFilterPanel like so:

JSON
{
  "type" : "UiSdlConnected<UiSdlFilterPanel>",
  "component" : {
    "title" : {
      "title" : "Demo Filter Panel"
    },
    "dataSpec" : {
      "fieldSets" : [ {
        "fields" : [ {
          "type" : "UiSdlFieldSetFilterFieldSetting",
          "fieldName" : "name",
          "label" : "Name",
          "filterElement" : {
            "type" : "CustomTextFieldFilterField",
            "inputElement" : {
              "placeholder": "Placeholder"
            }
          },
        } ]
      }]
    }
  }
}

This generates a filter panel with a single input.

Was this page helpful?