Custom

Overview

CustomField is a component that allows you to define custom form fields that can be used in your react application. You can use it to render any type of form field that you want, based on the type specified in the field configuration.

CustomField can be used either globally, by specifying it in the fieldComponents object passed to the FormProvider component, or locally, by specifying the Field prop in the field configuration when creating a form.

Example

import { Field, FieldConfig } from '@tutim/types';

export const CustomField: Field = ({ inputProps, fieldConfig }) => {
  const { value, onChange } = inputProps;
  const onClick = () => onChange(value + 2);
  return (
    <button type="button" onClick={onClick}>
      {fieldConfig.label}: {value}
    </button>
  );
};

Interface

Field

import { Field } from "@tutim/types";

This is an interface representing a custom form field. It includes the following properties:

type Field = (props: FieldProps) => JSX.Element;

FieldProps

import { FieldProps } from "@tutim/types";

This is an interface representing field props. It includes the following properties:

interface FieldProps {
  inputProps: InputProps;
  fieldConfig: FieldConfig;
  fieldState?: InputState;
}
  • ``inputProps: The control properties of the input, use it to control your field.

  • ``fieldConfig: The properties defined on FieldConfig, use it to customize your field (static).

InputProps

import { InputProps } from "@tutim/types";

This is an interface representing a form of field props. It includes the following properties:

interface InputProps {
  value: any;
  onChange: (newValue: InputProps["value"]) => void;
}
  • value: The current value of the field

  • onChange: The update method. Use it to update value.

FieldConfig

import { FieldConfig } from "@tutim/types";

This is an interface representing the configuration for a single form field. It includes the following properties:

interface FieldConfig {
  key: string;
  type: InputType;
  Field: Field;
  label?: string;
  isDisabled?: boolean;
  isRequired?: boolean;
  options?: Option[];
  defaultValue?: any;
}
  • key: A unique identifier for the field.

  • type: The type of input to use for the field, as specified by the InputType enumeration.

  • ``Field: A Field Component, use in order to replace the default (global) field set for this type, can only be used with InputType.Custom.

  • label: (optional) The label to display for the field.

  • isDisabled: (optional) A boolean value indicating whether the field should be disabled.

  • isRequired: (optional) A boolean value indicating whether the field is required.

  • options: (optional) An array of Option objects for use with InputType.Select and InputType.Radio fields.

  • defaultValue: (optional) The default value for the field.

InputState

import { InputState } from "@tutim/types";

This is an interface representing a form of field state props. It includes the following properties:

export interface InputState {
  invalid?: boolean;
  error?: { message?: string };
}
  • invalid: A boolean representing the validity of the field

  • error: Error object with message , usually a validation message

More examples

Basic example

To use CustomField, you will need to define the custom field component and specify the type that you want to use to reference it. You can do this by creating a new component that implements the Field interface from the @tutim/types library, and specifying the type in the field configuration when creating a form.

Here is an example of how to use CustomField to create a custom form field that renders a button that increments a number when clicked:

import { Field, FieldConfig } from '@tutim/types';

export const CustomField: Field = ({ inputProps, fieldConfig }) => {
  const { value, onChange } = inputProps;
  const onClick = () => onChange(value + 2);
  return (
    <button type="button" onClick={onClick}>
      {fieldConfig.label}: {value}
    </button>
  );
};

export const customFieldConfig: FieldConfig = {
  key: 'clicker',
  label: 'Click Me',
  type: 'custom',
  defaultValue: 0,
  Field: CustomField,
};

You can then use the customFieldConfig object to create a form with a custom field that increments its value by 2 every time the button is clicked:

import { TutimWizard } from '@tutim/fields';
import { customFieldConfig } from './CustomField';

const FormWithCustomField = () => {
  return <TutimWizard onSubmit={console.log} config={{ fields: [customFieldConfig] }} />;
};

Advanced example

You can use CustomField globally by specifying it in the fieldComponents object passed to the FormProvider component. This allows you to use your custom field in any form within your application, without having to specify the Field prop in the field configuration for each form.

To use CustomField globally, you will need to define the custom field component and add it to the fieldComponents object, using the type as the key and the field component as the value.

For example, you can use CustomField to create a custom form field that renders a button that increments a number when clicked, and use it in multiple forms by specifying it in the fieldComponents object passed to FormProvider:

import { TutimWizard } from '@tutim/fields';
import { FormProvider } from '@tutim/headless';
import { Field, FieldComponents, InputType } from '@tutim/types';

export const CustomField: Field = ({ inputProps, fieldConfig }) => {
  const { value, onChange } = inputProps;
  const onClick = () => onChange(value + 2);
  return (
    <button type="button" onClick={onClick}>
      {fieldConfig.label}: {value}
    </button>
  );
};

const fieldComponents: FieldComponents = {
  [InputType.Text]: ({ inputProps }) => <input {...inputProps} />,
  'custom-field': (fieldProps) => <CustomField {...fieldProps} />,
  // add any type of input and reference it by 'type'
};

const App = (): JSX.Element => {
  return (
    <div className="App">
      <FormProvider fieldComponents={fieldComponents}>
        <TutimWizard
          onSubmit={console.log}
          config={{
            fields: [
              { key: 'textField', label: 'Text Field', type: 'text' },
              { key: 'customField', label: 'Custom Field', type: 'custom-field', defaultValue: 0 },
            ],
          }}
        />
      </FormProvider>
    </div>
  );
};

export default App;

In this example, the CustomField component is added to the fieldComponents object with the key 'custom-field'. This means that any form field with an type of 'custom-field' will use the CustomField component to render the field.

Multiple custom fields

You can use multiple custom fields in your application by adding them to the fieldComponents object in the same way. For example, you can define a second custom field like this:

import { Field, FieldConfig } from '@tutim/types';

export const CustomField2: Field = ({ inputProps, fieldConfig }) => {
  const { value, onChange } = inputProps;
  const onClick = () => onChange(value + 1);
  return (
    <button type="button" onClick={onClick}>
      {fieldConfig.label}: {value}
    </button>
  );
};

export const customFieldConfig2: FieldConfig = {
  key: 'clicker2',
  label: 'Click Me 2',
  type: 'custom-field-2',
  defaultValue: 0,
  Field: CustomField2,
};

You can then add the CustomField2 component to the fieldComponents object, using the type 'custom-field-2' as the key:

import { TutimWizard } from '@tutim/fields';
import { FormProvider } from '@tutim/headless';
import { Field, FieldComponents, InputType } from '@tutim/types';
import { CustomField, customFieldConfig } from './CustomField';
import { CustomField2, customFieldConfig2 } from './CustomField2';

const fieldComponents: FieldComponents = {
  [InputType.Text]: ({ inputProps }) => <input {...inputProps} />,
  'custom-field': (fieldProps) => <CustomField {...fieldProps} />,
  'custom-field-2': (fieldProps) => <CustomField2 {...fieldProps} />,
  // add any other custom fields here, using the 'type' as the key
};

const App = (): JSX.Element => {
  return (
    <div className="App">
      <FormProvider fieldComponents={fieldComponents}>
        <TutimWizard
          onSubmit={console.log}
          config={{
            fields: [
              { key: 'textField', label: 'Text Field', type: 'text' },
              customFieldConfig, // use customFieldConfig to specify the 'type' and 'Field' props
              customFieldConfig2, // use customFieldConfig2 to specify the 'type' and 'Field' props
            ],
          }}
        />
      </FormProvider>
    </div>
  );
};

export default App;

In this example, the CustomField and CustomField2 components are added to the fieldComponents object with the keys 'custom-field' and 'custom-field-2', respectively. This means that any form field with an type of 'custom-field' will use the CustomField component to render the field, and any form field with an type of 'custom-field-2' will use the CustomField2 component to render the field.

Last updated