npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-hooks-useform

v0.1.86

Published

`react-hooks-useform` implements React hooks to enable an complete, lightweight form implementation for React. It works best with Material-UI components but can be used with native react inputs as well.

Downloads

964

Readme

react-hooks-useform

react-hooks-useform implements React hooks to enable an complete, lightweight form implementation for React. It works best with Material-UI components but can be used with native react inputs as well.

Installation

npm install --save react-hooks-useform

yarn add react-hooks-useform

Documentation

const [fieldProps, formProps] = useForm(formConfiguration)

formConfiguration

Prop|Type|Required|Description ----|----|--------|----------- fields|Array|Yes|Array of objects describing fieldConfiguration (see fieldConfiguration) submit|Function|Yes|(values)=>void Function calls when submit is triggered on form. validate|Function or Function[]|No| Called each time the form validates initialValues| Map<String, any>|No| Values to populate form fields. Can be lazy loaded. options|FormOptions|No|optional configurations

fieldConfiguration

Prop|Type|Required|Description ----|----|--------|----------- name|String|Yes|Name of the field. Will be used to pull data from initialValues. type|FieldTypes|No|Type of field data (text,boolean,select,number) helperText|String|No|Helper/Error text associated with the field optional|Boolean|No|Specifies if the field is optional or required for field validation requiredMessage|String|No|Message to display when required field validation fails (Defaults to 'Required') label|String|No|Label to display with the field normalize|Function|No|Normlalization function during onChange event to normalize data such as numbers/phones etc. value|any|No|Initial value used by the field (default: "") validate|(value: T, fieldName: String, getValues: () => IValues) => String|No|Validation function for field level validation. Can be combined with Form level validation. options|Array|No|Pass through options if type is select valueFromChange|(event: Object) => T|No|Helper function used if onChange handler needs to provide a value other than event.target.value

fieldProps Object

Prop|Type|Description ----|----|----------- error|Boolean|True if error exists on field, otherwise false helperText|String|Helper or error text label|String|Label provided by fieldConfiguration, Formatted as ${label} (optional) if field configured as an optional field. This can be customized in FormOptions value|any|Controlled value of the field onBlur|Function|Event triggered upon input blur onChange|Function|Event triggered upon input change

formProps Object

Prop|Type|Description ----|----|----------- Form|React.Component|Component used to wrap the form inputs submit|Function|Function to invoke when form should be submitted. Will trigger validation and if successful, trigger formConfiguration.submit addField|(field: fieldConfiguration) => void|Call to add a new field dynamically to the form removeField|(fieldName: String) => void|Call to remove a field dynamically form the form

fieldConfiguration

Prop|Type|Required|Description ----|----|--------|----------- optionalLabelFormatter|(label: String) => String|No|Function invoked to format labels for fields that are configured as optional

Examples

The following examples utilize Material-UI inputs

Simple Form

const SimpleForm = () => {
  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name' },
      { name: 'nickname', label: 'Nickname' },
    ],
  })

  return (
    <form.Form>
      <Flexbox flexDirection='column'>
        <TextField {...fields.fullName} />
        <TextField {...fields.nickname} />
      </Flexbox>
      <Button type='submit' onClick={form.submit}>Submit</Button>
    </form.Form>
  )
}

export { SimpleForm }

Optional Fields

const SimpleFormOptionalFields = () => {
  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name' },
      { name: 'nickname', label: 'Nickname', optional: true },
    ],
  })

  return (
    <form.Form>
      <Flexbox flexDirection='column'>
        <TextField {...fields.fullName} />
        <TextField {...fields.nickname} />
      </Flexbox>
      <Button type='submit' onClick={form.submit}>Submit</Button>
    </form.Form>
  )
}

export { SimpleFormOptionalFields }

Customize optional field prompt

const CustomizeOptionalPrompt = () => {
  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name' },
      { name: 'nickname', label: 'Nickname', optional: true },
    ],
    options: {
      optionalLabelFormatter: label => `${label} - not required`,
    },
  })

  return (
    <form.Form>
      <Flexbox flexDirection='column'>
        <TextField {...fields.fullName} />
        <TextField {...fields.nickname} />
      </Flexbox>
      <Button type='submit' onClick={form.submit}>Submit</Button>
    </form.Form>
  )
}

export { CustomizeOptionalPrompt }

Field level validation

const FieldValidation = () => {
  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name' },
      { name: 'nickname', label: 'Nickname', optional: true },
      { name: 'phone', label: 'Phone', validate: validatePhone },
    ],
  })

  return (
    <form.Form>
      <Flexbox flexDirection='column'>
        <TextField {...fields.fullName} />
        <TextField {...fields.nickname} />
        <TextField {...fields.phone} />
      </Flexbox>
      <Button type='submit' onClick={form.submit}>Submit</Button>
    </form.Form>
  )
}

export { FieldValidation }

Field input normalize

const normalizePhone = input => {
  let normalizedPhone
  ...
  return normalizedPhone
}

const FieldNormalize = () => {
  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name' },
      { name: 'nickname', label: 'Nickname', optional: true },
      { name: 'phone', label: 'Phone', validate: validatePhone, normalize: normalizePhone },
    ],
  })

  return (
    <form.Form>
      <Flexbox flexDirection='column'>
        <TextField {...fields.fullName} />
        <TextField {...fields.nickname} />
        <TextField {...fields.phone} />
      </Flexbox>
      <Button type='submit' onClick={form.submit}>Submit</Button>
    </form.Form>
  )
}

export { FieldNormalize }

Custom helper text

const HelperText = () => {
  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name' },
      { name: 'nickname', label: 'Nickname', optional: true },
      { name: 'phone', label: 'Phone', helperText: 'Please enter a phone number' },
    ],
  })

  return (
    <form.Form>
      <Flexbox flexDirection='column'>
        <TextField {...fields.fullName} />
        <TextField {...fields.nickname} />
        <TextField {...fields.phone} />
      </Flexbox>
      <Button type='submit' onClick={form.submit}>Submit</Button>
    </form.Form>
  )
}

export { HelperText }

Custom required field message

const CustomRequiredMessage = () => {
  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name', requiredMessage: 'Name is Required' },
      { name: 'nickname', label: 'Nickname', optional: true },
      { name: 'phone', label: 'Phone', requiredMessage: 'Phone is Required' },
    ],
  })

  return (
    <form.Form>
      <Flexbox flexDirection='column'>
        <TextField {...fields.fullName} />
        <TextField {...fields.nickname} />
        <TextField {...fields.phone} />
      </Flexbox>
      <Button type='submit' onClick={form.submit}>Submit</Button>
    </form.Form>
  )
}

export { CustomRequiredMessage }

Boolean field

const BooleanToggle = () => {
  const SwitchField = ({ label, error, helperText, ...rest }) => {
    return (
      <FormControlLabel
        control={(
          <Switch
            {...rest}
          />
        )}
        label={label}
      />
    )
  }

  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name' },
      { name: 'nickname', label: 'Nickname' },
      { name: 'isAdmin', label: 'Administrator', type: 'boolean' },
    ],
  })

  return (
    <form.Form>
      <Flexbox flexDirection='column'>
        <TextField {...fields.fullName} />
        <TextField {...fields.nickname} />
        <SwitchField {...fields.isAdmin} />
      </Flexbox>
      <Button type='submit' onClick={form.submit}>Submit</Button>
    </form.Form>
  )
}

export { BooleanToggle }

Number field

const NumberField = () => {
  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name' },
      { name: 'nickname', label: 'Nickname' },
      { name: 'age', label: 'Age', type: 'number', normalize: normalizeNumber },
    ],
  })

  return (
    <form.Form>
      <Flexbox flexDirection='column'>
        <TextField {...fields.fullName} />
        <TextField {...fields.nickname} />
        <TextField {...fields.age} />
      </Flexbox>
      <Button type='submit' onClick={form.submit}>Submit</Button>
    </form.Form>
  )
}

export { NumberField }

Select field

const SelectField = () => {
  const SelectComponent = ({
    label,
    error,
    value,
    helperText,
    children,
    options,
    ...rest
  }) => {

    return (
      <FormControl>
        {label && <InputLabel error={error}>{label}</InputLabel>}
        <Select
          value={value}
          {...rest}
          error={error}
        >
          {options.map((option) => {
            return <MenuItem key={options.value} value={option.value}>{option.label}</MenuItem>
          })}
        </Select>
        <FormHelperText error={error}>{helperText}</FormHelperText>
      </FormControl>
    )
  }

  const genderOptions = [
    { value: 'male', label: 'Male' },
    { value: 'female', label: 'Female' },
  ]

  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name' },
      { name: 'nickname', label: 'Nickname' },
      { name: 'gender', label: 'Gender', type: 'select', options: genderOptions },
    ],
  })

  return (
    <form.Form>
      <Flexbox flexDirection='column'>
        <TextField {...fields.fullName} />
        <TextField {...fields.nickname} />
        <SelectComponent {...fields.gender} />
      </Flexbox>
      <Button type='submit' onClick={form.submit}>Submit</Button>
    </form.Form>
  )
}

export { SelectField }

Initial values passed into form

const InitialValuesSet = ({ initialValues }) => {
  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name' },
      { name: 'nickname', label: 'Nickname' },
    ],
    initialValues,
  })

  return (
    <form.Form>
      <Flexbox flexDirection='column'>
        <TextField {...fields.fullName} />
        <TextField {...fields.nickname} />
      </Flexbox>
      <Button type='submit' onClick={form.submit}>Submit</Button>
    </form.Form>
  )
}

export { InitialValuesSet }

Dynamic fields

const DynamicFields = () => {

  const [fields, form] = useForm({
    fields: [
      { name: 'fullName', label: 'Full Name' },
      { name: 'nickname', label: 'Nickname' },
    ],
  })

  const [dynamicFields, dynamicForm] = useForm({
    fields: [
      { name: 'name', label: 'Name' },
      { name: 'label', label: 'Label' },
    ],
    submit: values => {
      const name = values.get('name')
      const label = values.get('label')
      form.addField({ name, label })
    },
  })

  return (
    <Flexbox flexDirection='column'>
      <dynamicForm.Form>
        <Flexbox>
          <TextField {...dynamicFields.name} />
          <TextField {...dynamicFields.label} />
          <Button type='submit' onClick={dynamicForm.submit}>Add Field</Button>
        </Flexbox>
      </dynamicForm.Form>
      <Divider style={{ margin: '24px 16px 8px 16px' }} />
      <form.Form>
        <Flexbox flexDirection='column'>
          <TextField {...fields.fullName} />
          <TextField {...fields.nickname} />
          {Object.keys(fields)
            .filter(key => (key !== 'fullName' && key !== 'nickname'))
            .map(key => (
              <Flexbox key={key}>
                <TextField {...fields[key]} />
                <Button onClick={() => form.removeField(key)}>X</Button>
              </Flexbox>
            ))
          }
        </Flexbox>
        <Button type='submit' onClick={form.submit}>Submit</Button>
      </form.Form>
    </Flexbox>
  )
}

export { DynamicFields }