Foundation

Main View


Components

Charts

Dialogs

Framer Animations

Forms

Grids

Typography


Utils


EzForm


Package: @uireact/ezforms

v0.1.0
‼️ Beta

Create validated forms quickly and easily with a schema object

1. Make sure you install peer dependencies first:

Expand peer dependencies

2. Install package:

npm i -S @uireact/ezforms

The EzForm component builds a form automatically out of a schema, the form will be automatically validated using the specifics on the schema. The schema is created using the @uireact/validator util:

The field() fn exposes a function: ezMetadata() which is a chainable function that can be used to pass metadata to each of the schema fields:

const validator = new UiValidator();

const schema = {
  name: validator.field('text').ezMetadata({ label: 'First Name', icon: 'User' }).present(),
  birthday: validator.field('date').ezMetadata({ label: 'When is your birthday?', icon: 'Party', dateFormat: 'yyyy/mm/dd' }).present(),
  age: validator.field('numeric').ezMetadata({ label: 'How old are you?', icon: 'Sun' }).present().greaterThan(18, "You have to be older than 18 years old"),
  email: validator.field('email').ezMetadata({ label: 'Enter your email', icon: 'Mail' }).present(),
  type: validator.field('choice').ezMetadata({ label: 'Account type' }).present("You have to select the type of account").oneOf(['user', 'admin', 'editor']),
  description: validator.field('text').ezMetadata({ label: 'Description', paragraph: true }).optional(),
  terms: validator.field('boolean').ezMetadata({ label: 'Accept terms and conditions' }).present("You have to accept our terms and conditions")
};

From there you can continue to add any specific validation to each field.

Once the schema is complete we can pass it as a prop and this will be the outcome:

  <EzFormExample />

The complete code for the EzFormExample:

const validator = new UiValidator();

const schema = {
  name: validator
    .field('text')
    .ezMetadata({ label: 'First Name', icon: 'User' })
    .present(),
  birthday: validator
    .field('date')
    .ezMetadata({ label: 'When is your birthday?', icon: 'Party', dateFormat: 'yyyy/mm/dd' })
    .present(),
  age: validator
    .field('numeric')
    .ezMetadata({ label: 'How old are you?', icon: 'Sun' })
    .present()
    .greaterThan(18, "You have to be older than 18 years old"),
  phone: validator
    .field('phone')
    .ezMetadata({ label: 'Your phone' })
    .optional(),
  email: validator
    .field('email')
    .ezMetadata({ label: 'Your email', icon: 'Mail' }).present()
    .when('phone', validator.is().present())
    .run(validator.is().optional())
    .else(validator.is().present("The email is required if you don't provide your phone number.")),
  type: validator
    .field('choice')
    .ezMetadata({ label: 'Account type' })
    .present("You have to select the type of account")
    .oneOf(['user', 'admin', 'editor']),
  description: validator
    .field('text')
    .ezMetadata({ label: 'Description', paragraph: true })
    .optional(),
  terms: validator
    .field('boolean')
    .ezMetadata({ label: 'Accept terms and conditions' })
    .present("You have to accept our terms and conditions")
};

export const EzFormExample = () => {  
  const onSubmit = useCallback((e: FormEvent<HTMLFormElement>, data: UiValidatorData) => {
    e.preventDefault();
    console.log(data);
  }, []);
  const onCancel = useCallback(() => {
    console.log('Cancel triggered');
  }, []);

  return (
    <UiEzForm 
      schema={schema} 
      submitLabel='Save' 
      cancelLabel='Cancel' 
      onSubmit={onSubmit} 
      onCancel={onCancel} 
      initialData={{ birthday: '1992/12/03' }} 
    />
  )
};

The field() function will set a initial type for that specific field in the schema, based on this we will render the input that is more suitable for it:

  text -> <UiInput type="text" />
  text with .ezMetadata({ paragraph: true }) -> <UiTextarea />
  numeric -> <UiInput type="number" />
  email -> <UiInput type="email" />
  phone -> <UiInput type="text" />
  date -> <UiDatepicker />
  boolean -> <UiSwitch />
  choice -> <UiSelect />

The EzForm can be initialized with an initial data this is useful for use cases where you already have some data and the user need to modify or complete it. The initialData object MUST match a field in the schema, ONLY the properties in the object that matches a field in the schema will be used.

For instance, for this schema:

const schema = {
  name: validator.field('text').ezMetadata({ label: 'First Name', icon: 'User' }).present()
};

The initial data should be something like:

const initialData = {
  name: 'Some user data'
};

The EzForm will run validations when user clicks submits the form, all validations are run based on the schema passed.

Each of the validation functions can get their own error message, so if you haven't already you should check the @uireact/validator doc page to learn how to set up the schema.

The conditional validations are also supported, so if you use .when() the validations in the form will be ran conditionally, to learn more about this go to Conditional validations;

Client side

The EzForm exposes a onSubmit callback that you can attach to it and will be triggered when the user submits the form and the validation passes. If you want to handle the submit with javascript then here you would do the preventDefault like this:

export const YourFormComponent = () => {  
  const onSubmit = useCallback((e: FormEvent<HTMLFormElement>, data: UiValidatorData) => {
    e.preventDefault(); // Here you can prevent default to handle the submit with javascript
    console.log(data);
  }, []);

  return (
    <UiEzForm 
      schema={{}} 
      submitLabel='Save' 
      cancelLabel='Cancel' 
      onSubmit={onSubmit} 
    />
  )
};

Browser apis

If you want to let the browser to continue with its normal submit then you don't need to pass any and the form will be triggered and submitted as usual. Important, make sure you pass the action and method prop so the submit goes as you plan to where you plan it to go.

Inline (Default)

By default the form buttons render inline:

  <UiEzForm
    schema={{
      name: new UiValidator().field("text").ezMetadata({ label: "Name:" })
    }}
    submitLabel='Save'
    cancelLabel='Cancel'
  />

Stacked

By default the form buttons render inline, although you can pass buttonsAlignment prop as stacked and the buttons are going to render stacked:

  <UiEzForm 
    schema={{
      name: new UiValidator().field("text").ezMetadata({ label: "Name:" })
    }}
    buttonsAlignment='stacked'
    submitLabel='Save' 
    cancelLabel='Cancel' 
  />