{"id":14981880,"url":"https://github.com/pacdiv/hoc-form","last_synced_at":"2025-10-29T09:30:19.286Z","repository":{"id":99499456,"uuid":"129362627","full_name":"pacdiv/hoc-form","owner":"pacdiv","description":"Concise form validation for React! 🚀","archived":false,"fork":false,"pushed_at":"2018-07-30T06:48:31.000Z","size":220,"stargazers_count":16,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-02T00:24:55.349Z","etag":null,"topics":["babeljs","form","form-builder","form-validation","higher-order-component","javascript","react","reactjs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pacdiv.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-13T07:03:52.000Z","updated_at":"2018-09-19T13:38:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"625cb0aa-7581-4f62-a022-4a19be187280","html_url":"https://github.com/pacdiv/hoc-form","commit_stats":{"total_commits":28,"total_committers":1,"mean_commits":28.0,"dds":0.0,"last_synced_commit":"fd9a5ee7c5133161b7c2a25f6422aa7c77c93134"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pacdiv%2Fhoc-form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pacdiv%2Fhoc-form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pacdiv%2Fhoc-form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pacdiv%2Fhoc-form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pacdiv","download_url":"https://codeload.github.com/pacdiv/hoc-form/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238795481,"owners_count":19531754,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["babeljs","form","form-builder","form-validation","higher-order-component","javascript","react","reactjs"],"created_at":"2024-09-24T14:04:25.744Z","updated_at":"2025-10-29T09:30:18.832Z","avatar_url":"https://github.com/pacdiv.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# hoc-form • ![Travis](https://img.shields.io/travis/pacdiv/hoc-form.svg) ![Coveralls github](https://img.shields.io/coveralls/github/pacdiv/hoc-form.svg) ![npm](https://img.shields.io/npm/v/hoc-form.svg) ![license](https://img.shields.io/github/license/pacdiv/hoc-form.svg)\n\nTired of writing custom form validation on every project you might work on? Let’s try `hocForm`, form validation on React has rarely been so simple! 🤗\n\n# Requirements\nhocForm needs at least react@16.3.1 and react-dom@16.3.1 to work.\n\n# Installation\nUsing `npm`:\n\n```\nnpm install --save hoc-form\n```\n\n`yarn add hoc-form` works fine too!\n\n# Usage\n```javascript\nimport React from 'react';\nimport hocForm, { Field } from 'hoc-form';\n\n// First, we need a input component to render our text field\nfunction Input({\n  input = {},\n  label = '',\n  meta = {},\n  placeholder = '',\n  type = 'text',\n}) {\n  return (\n    \u003cdiv\u003e\n      \u003clabel\u003e\n        {label}\n      \u003c/label\u003e\n      \u003cinput\n        placeholder={placeholder}\n        type={type}\n        {...input}\n        onBlur={e =\u003e input.onBlur \u0026\u0026 input.onBlur(e.target.value)}\n        onChange={e =\u003e input.onChange(e.target.value)}\n      /\u003e\n      {meta.error \u0026\u0026 \u003cspan\u003e{meta.error}\u003c/span\u003e}\n    \u003c/div\u003e\n  );\n}\n\n// Then, we need to create our form component and its helpers\nconst unavailableUsernames = [\n  'elonmusk',\n  'ironman',\n  'lukeskywalker',\n];\n\nfunction validateLogin(value = '') {\n  if (value.trim() === '') {\n    return Promise.reject('Please enter an username');\n  }\n\n  return unavailableUsernames.includes(value)\n    ? Promise.reject('This username is unavailable')\n    : Promise.resolve()\n}\n\nfunction validatePassword(value = '') {\n  if (value.trim().length \u003c 6) {\n    return Promise.reject('Password must contain 6 characters or more');\n  }\n\n  return Promise.resolve();\n}\n\nfunction Form({ onSubmit }) {\n  return (\n    \u003cform onSubmit={onSubmit} noValidate\u003e\n      \u003cField\n        name=\"login\"\n        component={Input}\n        props={{\n          label: 'Login *',\n          onBlur: value =\u003e validateLogin(value),\n          placeholder: 'elonmusk',\n          type: 'string',\n        }}\n      /\u003e\n      \u003cField\n        name=\"pwd\"\n        component={Input}\n        props={{\n          label: 'Password *',\n          type: 'password',\n        }}\n      /\u003e\n      \u003cbutton type=\"submit\"\u003eSign up\u003c/button\u003e\n    \u003c/form\u003e\n  );\n}\n\n// Finally, an export of our wrapped form component\n// with a validation function\nexport default hocForm({\n  validate(values, props) {\n    let errors = {};\n    const errorCatcher = (key, callback, ...args) =\u003e (\n      callback(values[key], args)\n        .catch(error =\u003e ({ [key]: error }))\n    );\n\n    return Promise.all([\n      errorCatcher('login', validateLogin),\n      errorCatcher('pwd', validatePassword),\n    ]).then((errors) =\u003e {\n      const results = errors.reduce((acc, item) =\u003e ({ ...acc, ...item }), {});\n      return Object.keys(results).length ? Promise.reject(results) : Promise.resolve();\n    });\n  }\n})(Form);\n```\nPlease check out the [complete demo](https://github.com/pacdiv/hoc-form/tree/master/demo)! 🚀\n\n# API\n\n## `hocForm({ options })(MyFormComponent) =\u003e React.Component`\nRenders your `MyFormComponent` contexted with `hocForm`.\n\nTwo arguments are required:\n- An `options` object to define the `validate` function and optional `initialValues`\n- A form `React.Component` to render.\n\n### `options.validate(values, props) =\u003e Promise`\nValidates the form on submit.\n\nArguments:\n1. `values` (`Object`): An object containing all fields keys and their value.\n2. `props` (`Object`): An object containing all props provided to `MyFormComponent`.\n\nReturns:\n- A promise:\n  - On success, your must return `Promise.resolve()`\n  - In case of failure, your must return `Promise.reject({})`. The object parameter must contain every field key with its error (type of string or else, depends on how your components used with `Field` are designed).\n\nExample, with errors as strings:\n```javascript\nfunction validate(values, props) {\n  let errors = {};\n\n  if (values.username) {\n    if (!props.isUsernameAvailable(values.username)) {\n      errors = { ...errors, username: 'This username is unavailable' };\n    }\n  } else {\n    errors = { ...errors, username: 'Please enter an username' };\n  }\n\n  if (!values.password) {\n    errors = { ...errors, password: 'Please enter a password' };\n  }\n\n  return Object.keys(errors).length\n    ? Promise.reject(errors)\n    : Promise.resolve();\n}\n```\n\n### `options.initialValues: Object`\nObject containing all initial values following fields keys.\n\nExample:\n```javascript\ninitialValues: {\n  country: 'United Kingdom',\n  phone: '+44',\n}\n```\n\n### `MyFormComponent: React.Component`\nA `React.Component` rendering a form including some `hocForm.Field` items.\n\nExample:\n```javascript\nfunction Form({ onSubmit }) {\n  return (\n    \u003cform onSubmit={onSubmit} noValidate\u003e\n      \u003cField\n        name=\"login\"\n        component={Input}\n        props={{\n          label: 'Login *',\n          type: 'string',\n        }}\n      /\u003e\n    /\u003e\n  );\n}\n```\n\nPlease check out a [complete example here](https://github.com/pacdiv/hoc-form/tree/master/demo).\n\n## `Field({ options }) =\u003e React.Component`\nRenders a form field, contexted with `hocForm`.\n\n### `options.name: String`\nThe name used in your `options.validate` function.\n\nExample:\n```javascript\n\u003cField\n  name=\"login\"\n/\u003e\n```\n\n### `options.component: React.Component`\nThe `React.Component` rendered by `Field`.\n\nExample:\n```javascript\n\u003cField\n  component={Input}\n/\u003e\n```\n\n### `options.props: Object`\nThe properties provided to the `component` parameter.\n\nExample:\n```javascript\n\u003cField\n  props={{\n    label: 'Login *',\n    onBlur: (value, otherValues) =\u003e Promise.resolve(),\n    placeholder: 'elonmusk',\n    type: 'string',\n  }}\n/\u003e\n```\n\nPlease check out a [complete example here](https://github.com/pacdiv/hoc-form/tree/master/demo).\n\n## Which extra-props my components receive from `Field`?\nComponents used in `Field` must handle the two following properties: `input` and `meta`. Please check out the description below.\n\n### `input.onChange(value: *)`\nAllows to dispatch the new value of the field to the `hocForm` state. With this, all you have to do is to run `input.onChange(theNewValue)` to allow `hocForm` to use this new value at validation.\n\nExample:\n```javascript\nfunction TextInput({\n  input = {},\n}) {\n  return (\n    \u003cinput\n      type=\"text\"\n      onChange={e =\u003e input.onChange(e.target.value)}\n    /\u003e\n  );\n}\n```\n\n### `input.onBlur(value: *, values: Object) =\u003e Promise`\nAllows to run a validation on blur, the `onBlur` callback setted as property of the `Field`.\n\nExample:\n```javascript\nfunction TextInput({\n  input = {},\n}) {\n  return (\n    \u003cinput\n      type=\"text\"\n      onBlur={e =\u003e input.onBlur \u0026\u0026 input.onBlur(e.target.value)}\n    /\u003e\n  );\n}\n```\n\n**Note:**\nWhen `Field` runs the optional `onBlur` callback received from its `props` property, it runs this callback with two arguments:\n- `value: *`, which is the current value of the `Field`;\n- `values: Object`, object containing all fields keys with their respective value. As example, this argument can be useful if you need to compare a « confirmation password » field with a previous « create password » field.\n\nThis callback must a return a Promise:\n- `Promise.resolve()` if this blur validation succeeds;\n- `Promise.reject(error)` in case of failure.\n\nExample:\n```javascript\n\u003cField\n  name=\"confirmPwd\"\n  component={Input}\n  props={{\n    label: 'Password confirmation *',\n    type: 'password',\n    onBlur: (currentValue, values) =\u003e (\n      currentValue.trim() !== values.firstPassword)\n        ? Promise.reject('Please enter the same password as below')\n        : Promise.resolve()\n    ),\n  }}\n/\u003e\n```\n\n### `options.meta: Object`\n\nObject containing about a potential error on the field.\n\nExample:\n```javascript\nfunction TextInput({\n  meta = {},\n  input = {},\n}) {\n  return (\n    \u003cReact.Fragment\u003e\n      \u003cinput\n        type=\"text\"\n        onBlur={e =\u003e input.onBlur \u0026\u0026 input.onBlur(e.target.value)}\n      /\u003e\n      {meta.error \u0026\u0026 \u003cspan\u003e{meta.error}\u003c/span\u003e}\n    \u003c/React.Fragment\u003e\n  );\n}\n```\n\nPlease check out a [complete example here](https://github.com/pacdiv/hoc-form/tree/master/demo).\n\n# License\nhocForm is [MIT licensed](https://github.com/pacdiv/hoc-form/blob/master/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpacdiv%2Fhoc-form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpacdiv%2Fhoc-form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpacdiv%2Fhoc-form/lists"}