{"id":18817864,"url":"https://github.com/vitorluizc/vue-form-container","last_synced_at":"2025-04-13T23:25:12.676Z","repository":{"id":57395992,"uuid":"150784110","full_name":"VitorLuizC/vue-form-container","owner":"VitorLuizC","description":"👜 A Provider Component that encapsulate your forms and handle their states and validations.","archived":false,"fork":false,"pushed_at":"2019-03-20T23:30:33.000Z","size":104,"stargazers_count":24,"open_issues_count":1,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-09T06:35:47.923Z","etag":null,"topics":["javascript","vue","vue-component","vue-form","vue-form-validation","vue-validate","vue-validation","vue-validator"],"latest_commit_sha":null,"homepage":"","language":"Vue","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/VitorLuizC.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-09-28T19:08:33.000Z","updated_at":"2023-09-10T17:55:19.000Z","dependencies_parsed_at":"2022-09-09T16:00:54.816Z","dependency_job_id":null,"html_url":"https://github.com/VitorLuizC/vue-form-container","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VitorLuizC%2Fvue-form-container","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VitorLuizC%2Fvue-form-container/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VitorLuizC%2Fvue-form-container/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VitorLuizC%2Fvue-form-container/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/VitorLuizC","download_url":"https://codeload.github.com/VitorLuizC/vue-form-container/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248795347,"owners_count":21162754,"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":["javascript","vue","vue-component","vue-form","vue-form-validation","vue-validate","vue-validation","vue-validator"],"created_at":"2024-11-08T00:13:44.342Z","updated_at":"2025-04-13T23:25:12.641Z","avatar_url":"https://github.com/VitorLuizC.png","language":"Vue","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vue-form-container\n\n[![min size](https://img.shields.io/bundlephobia/min/vue-form-container.svg)](https://bundlephobia.com/result?p=vue-form-container)\n[![min + zip size](https://img.shields.io/bundlephobia/minzip/vue-form-container.svg)](https://bundlephobia.com/result?p=vue-form-container)\n[![License](https://img.shields.io/npm/l/vue-form-container.svg)](https://github.com/VitorLuizC/vue-form-container/blob/master/LICENSE)\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FVitorLuizC%2Fvue-form-container.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FVitorLuizC%2Fvue-form-container?ref=badge_shield)\n\nA _Provider Component_ that encapsulate your forms and handle their states and validations. Under the hood it uses [`valite`](https://VitorLuizC/valite), a light and concise validator engine that works on asynchrony. The idea of having a component handling the states and validations of the forms I took from [`formik`](https://github.com/jaredpalmer/formik) and [`vue-final-form`](https://github.com/egoist/vue-final-form).\n\n## Installation\n\nThis library is published in the NPM registry and can be installed using any compatible package manager.\n\n```sh\nnpm install --save vue-form-container\n\n# Use the command below if you're using Yarn.\nyarn add vue-form-container\n```\n\n## Getting Started\n\nWrap your form, or wrapper element, with the `FormContainer` component passing the initial state of the fields and a scheme with the validations. Use `slot-scope` to receive the `FormContainer` scope with fields, errors, and so on.\n\n```vue\n\u003ctemplate\u003e\n  \u003cform-container :initial=\"{ name: '' }\" :schema=\"{\n    name: [\n      (name) =\u003e name.length \u003e 0 || 'Name is required.'\n    ]\n  }\"\u003e\n    \u003cdiv slot-scope=\"{ fields, errors }\"\u003e\n      \u003clabel\u003eName\u003c/label\u003e\n      \u003cinput v-model=\"fields.name\" type=\"text\" /\u003e\n      \u003cspan\u003e{{ errors.name }}\u003c/span\u003e\n    \u003c/div\u003e\n```\n\n\u003e `FormContainer` is a renderless component, so it can receive just a single element as slot.\n\nYou can change the form field states and perform their validations using `update` functions or by changing the state of the` fields` object, which is a Proxy.\n\n\u003e Due to platform limitations, fields (properties) need to be defined in **`schema`** or **`initial`**. If you don't want to initialize the value of a field, use `undefined` for it in **`initial`** or an empty list of validations in **`schema`**.\n\u003e\n\u003e **It is extremely important that the field exists on at least one of the objects.**\n\u003e\n\u003e ```vue\n\u003e \u003ctemplate\u003e\n\u003e   \u003cform-container :initial=\"{ empty: undefined }\"\u003e\n\u003e   \u003c!-- OR --\u003e\n\u003e   \u003cform-container :schema=\"{ empty: [] }\"\u003e\n\u003e ```\n\nTo use the `FormContainer` validations, fields and errors outside the template you should use a `ref` as in the example:\n\n```vue\n\u003ctemplate\u003e\n  \u003cform-container ref=\"form\" ... \u003e\n    \u003cform ... @submit.prevent=\"onSubmit()\"\u003e\n      ...\n      \u003cbutton type=\"submit\"\u003eSign In\u003c/button\u003e\n    \u003c/form\u003e\n  \u003c/form-container\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\n  export default {\n    methods: {\n      async onSubmit () {\n        // A FormContainer instance to handle fields, validate methods and other stuff.\n        const form = this.$refs.form;\n\n        await form.validateForm();\n        if (!form.isValid)\n          return;\n\n        console.log('fields', form.fields);\n      }\n    }\n  };\n\u003c/script\u003e\n```\n\n## API\n\n### `FormContainer` props\n\nName    | Type              | Description\n--------|-------------------|-------------\nschema  | `ValidatorSchema` | Schema of validators for form fields.\ninitial | `Object`          | Initial state of form fields.\n\n\u003e #### About `ValidatorSchema` type\n\u003e\n\u003e `ValidatorSchema` is an object whose key is the name of the field and the value is a collection of validations. Validations are just functions that receive the value of the field and return` true` if it is valid and a `string` with the error message if it is invalid, these functions can also be asynchronous by returning a Promise that returns the same values (`true` or `string` with the error message).\n\u003e\n\u003e ```typescript\n\u003e type Validator = (value: any) =\u003e true | string | Promise\u003ctrue | string\u003e;\n\u003e\n\u003e type ValidatorSchema = { [field: string]: Validator[]; };\n\u003e\n\u003e ...\n\u003e\n\u003e const schema: ValidatorSchema = {\n\u003e   name: [\n\u003e     (name) =\u003e !!name.trim() || 'Name is required.',\n\u003e\n\u003e     async (name) =\u003e {\n\u003e       const isRepeated = await services.isRepeatedName(name);\n\u003e       return !isRepeated || 'Name is repeated.';\n\u003e     }\n\u003e   ]\n\u003e };\n\u003e ```\n\n### `FormContainer` properties and methods (also received by slot-scope)\n\nName          | Type                                  | Description\n--------------|---------------------------------------|:------------\nisValid       | `boolean`                             | Indicates if form fields are valid.\nisLoading     | `boolean`                             | Indicates if there's a validation running.\nerrors        | `MessageSchema`                       | Error scheme of form fields.\nfields        | `Proxy\u003c{ [field: string]: any }\u003e`     | Proxy with form fields. It uses getters to get the state of the field and setters to update it.\nupdate        | `(field: string, value: any) =\u003e void` | Updates the state of the `field` using the `value`.\nvalidateField | `(field: string) =\u003e Promise\u003cvoid\u003e`    | Executes the schema validations for the `field` field.\nvalidateForm  | `() =\u003e Promise\u003cvoid\u003e`                 | Executes the validations on all fields specified in the schema.\n\n\u003e #### About `MessageSchema` type\n\u003e\n\u003e `MessageSchema` is a reflection of the scheme used to define the validations and contains the error messages (or `null`) for the fields.\n\u003e\n\u003e ```typescript\n\u003e type Message = string | null;\n\u003e\n\u003e type MessageSchema = { [field: string]: Message; };\n\u003e\n\u003e ...\n\u003e\n\u003e const errors: MessageSchema = {\n\u003e   name: 'Use first and last name.',\n\u003e   email: 'E-Mail is required.',\n\u003e   phone: null, // No error message, because validators have returned true.\n\u003e };\n\u003e ```\n\n## Example\n\n```vue\n\u003ctemplate\u003e\n  \u003cform-container ref=\"form\" :schema=\"schema\" :initial=\"initial\"\u003e\n    \u003cform slot-scope=\"{ fields, errors, submit }\" @submit.prevent=\"onSubmit()\"\u003e\n      \u003cfieldset\u003e\n        \u003clabel\u003eName\u003c/label\u003e\n        \u003cinput type=\"text\" v-model=\"fields.name\" /\u003e\n        \u003cspan v-if=\"errors.name\"\u003e{{ errors.name }}\u003c/span\u003e\n      \u003c/fieldset\u003e\n\n      \u003cfieldset\u003e\n        \u003clabel\u003eE-Mail\u003c/label\u003e\n        \u003cinput type=\"email\" v-model=\"fields.email\" /\u003e\n        \u003cspan v-if=\"errors.name\"\u003e{{ errors.email }}\u003c/span\u003e\n      \u003c/fieldset\u003e\n\n      \u003cbutton type=\"submit\"\u003eSign Up\u003c/button\u003e\n    \u003c/form\u003e\n  \u003c/form-container\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\n  import FormContainer from 'vue-form-container';\n  import * as services from './services';\n\n  // FormContainer schema to validate fields.\n  const schema = {\n    name: [\n      (name) =\u003e !!name.trim() || 'Name is required.'\n    ],\n    email: [\n      (email) =\u003e !!email.trim() || 'E-Mail is required.',\n      (email) =\u003e /^.+@.+\\..+$/.test(email) || 'E-Mail is invalid.',\n      async (email) =\u003e {\n        const isRepeated = await services.isRepeatedEMail(email);\n        return isRepeated || 'E-Mail is already registered.'\n      }\n    ]\n  };\n\n  export default {\n    components: { FormContainer },\n    data () {\n      return {\n        schema,\n\n        // FormContainer fields initial state.\n        initial: { name: '', email: '' }\n      };\n    },\n    methods: {\n      async onSubmit () {\n        await this.$refs.form.validateForm();\n\n        if (!this.$refs.form.isValid)\n          return;\n\n        console.log('submit fields', this.$refs.form.fields);\n      }\n    }\n  };\n\u003c/script\u003e\n```\n\n## License\n\nReleased under [MIT License](./LICENSE).\n\n\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FVitorLuizC%2Fvue-form-container.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FVitorLuizC%2Fvue-form-container?ref=badge_large)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvitorluizc%2Fvue-form-container","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvitorluizc%2Fvue-form-container","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvitorluizc%2Fvue-form-container/lists"}