<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Alex Liu</title>
    <description>The latest articles on Forem by Alex Liu (@minighost).</description>
    <link>https://forem.com/minighost</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F396103%2F5edcc7d3-6bc8-4eab-8c2f-3445fcc09fbe.jpeg</url>
      <title>Forem: Alex Liu</title>
      <link>https://forem.com/minighost</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/minighost"/>
    <language>en</language>
    <item>
      <title>Vorms: Vue form validation with Composition API</title>
      <dc:creator>Alex Liu</dc:creator>
      <pubDate>Sun, 18 Dec 2022 02:48:56 +0000</pubDate>
      <link>https://forem.com/minighost/vorms-vue-form-validation-with-composition-api-5dhg</link>
      <guid>https://forem.com/minighost/vorms-vue-form-validation-with-composition-api-5dhg</guid>
      <description>&lt;p&gt;Forms are part of our lives on the web. We use them to take surveys, sign up for workshops, and apply for gym memberships. However, form validation and state management are difficult points in web front-end development.&lt;/p&gt;

&lt;p&gt;While Vue's &lt;code&gt;v-model&lt;/code&gt; directive helps us simplify form input binding, we still have a lot of details to deal with, such as: accessibility, validation, and printing out error messages for each field to ensure the correct value is submitted. .. etc.&lt;/p&gt;

&lt;p&gt;So, I decided to build a library, which should be the simplest and most flexible, and just only focus on the core logic.&lt;/p&gt;

&lt;p&gt;The final result: &lt;strong&gt;Vorms - Vue Form Validation with Composition API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FMini-ghost%2Fvorms%2Fmain%2Fdocs%2Fpublic%2Flogo.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FMini-ghost%2Fvorms%2Fmain%2Fdocs%2Fpublic%2Flogo.svg" alt="Vorms - Form Validation with Vue Composition API"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Vorms
&lt;/h2&gt;

&lt;p&gt;Vorms is a form validation and state management library based on the Vue 3 Composition API. It has many features, as below:&lt;/p&gt;

&lt;h3&gt;
  
  
  💪 Type Strong
&lt;/h3&gt;

&lt;p&gt;TypeScript is the trend of modern front-end development. Even for projects developed using JavaScript, choosing a library developed based on TypeScript can allow us to obtain richer intelligence perception during the development process and reduce the mental burden of use.&lt;/p&gt;

&lt;p&gt;Vorms is written in TypeScript, with detailed TSDocs added to the core API. Users can easily understand how to use it and make the development experience better.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠 Composition API
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://vuejs.org/guide/extras/composition-api-faq.html" rel="noopener noreferrer"&gt;Composition API&lt;/a&gt; for better logic reuse. Vorms uses the Composition API, which allows us to easily extend the logic to face different scenarios.&lt;/p&gt;

&lt;p&gt;Vorms has only four composition APIs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;useForm()&lt;/code&gt;&lt;br&gt;
A composition API that surrounds our entire form and manages the form state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;useField()&lt;/code&gt;&lt;br&gt;
A composition API that will return specific field value, meta (state) and attributes, you can also add validation for that field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;useFieldArray()&lt;/code&gt;&lt;br&gt;
A composition API that will return specific fields values, meta (state), attributes and provides common operation helpers, you can also add a validation for those fields.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;useFormContext()&lt;/code&gt;&lt;br&gt;
A composition API that allow you access the form context. This is useful with deeply nested component structures.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This follow is the Vorms basic usage:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;setup script&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useForm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vorms/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;starterOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sprigatito&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fuecoco&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Quaxly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleReset&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;initialValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// If `onSubmit()` function is synchronous, &lt;/span&gt;
  &lt;span class="c1"&gt;// you need to call setSubmitting(false) yourself.&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;attrs&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pokemon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;template&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;submit=&lt;/span&gt;&lt;span class="s"&gt;"handleSubmit"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;reset=&lt;/span&gt;&lt;span class="s"&gt;"handleReset"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"pokemon"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;First partner Pokémon&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"pokemon"&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt; &lt;span class="na"&gt;v-bind=&lt;/span&gt;&lt;span class="s"&gt;"attrs"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"item in starterOptions"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt; &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      {{ item }}
    &lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"reset"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Reset&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Get Start&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Vorms' pure Composition API makes it adaptable to any UI library, in follow is vorms work with &lt;a href="https://github.com/vuetifyjs/vuetify" rel="noopener noreferrer"&gt;Vuetify&lt;/a&gt; and &lt;a href="https://github.com/element-plus/element-plus" rel="noopener noreferrer"&gt;Element-Plus&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/vorms-vuetify?embed=1&amp;amp;file=src/App.vue&amp;amp;hideExplorer=1&amp;amp;hideNavigation=1&amp;amp;view=preview&amp;amp;ctl=1" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/vorms-with-element-plus?embed=1&amp;amp;file=src/App.vue&amp;amp;hideExplorer=1&amp;amp;hideNavigation=1&amp;amp;view=preview&amp;amp;ctl=1" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Refer &lt;a href="https://vorms.mini-ghost.dev/" rel="noopener noreferrer"&gt;documentations&lt;/a&gt; for more details.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  💡 Validation
&lt;/h3&gt;

&lt;p&gt;Regarding form validation, we are most concerned about two issues, one is &lt;strong&gt;when to call validation&lt;/strong&gt;, and the other is &lt;strong&gt;how to call validation&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  When to call validation
&lt;/h4&gt;

&lt;p&gt;In some cases we want to have different form validation times before and after the first form submission. For example, to validate a form only if it is submitted before the first submission, if any field is invalid, validation will be re-run when typing into that field&lt;/p&gt;

&lt;p&gt;Vorms provides two props to control these behaviors, &lt;code&gt;validationMode&lt;/code&gt; and &lt;code&gt;reValidationMode&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useForm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vorms/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleReset&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;initialValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;validationMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// default is `submit`&lt;/span&gt;
  &lt;span class="na"&gt;reValidationMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// default is `change`&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;attrs&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By applying these two props, we can better control the timing of form validation. We won't validate the form too early, and yell at the user too early, making the user feel annoyed.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to call validation
&lt;/h4&gt;

&lt;p&gt;At present, there are many schema validation libraries on the npm package, such as: &lt;a href="https://github.com/jquense/yup" rel="noopener noreferrer"&gt;Yup&lt;/a&gt;, &lt;a href="https://github.com/colinhacks/zod" rel="noopener noreferrer"&gt;Zod&lt;/a&gt;...etc.&lt;/p&gt;

&lt;p&gt;In Vorms, we don't provide any built-in validation rules. Our goal is to allow every developer to freely choose a schema validation library or write their own validation function according to their own habits.&lt;/p&gt;

&lt;p&gt;To this end, we wrote some validation resolvers (&lt;a href="https://www.npmjs.com/package/@vorms/resolvers" rel="noopener noreferrer"&gt;@vorms/resolvers&lt;/a&gt;) so that we can easily integrate third-party schema validation libraries. And if you write the form validation rules yourself, you don't have to worry about redundant code turns your project into a monster with excess body fat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vorms Example - Validate With Yup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/vorms-validate-with-yup?embed=1&amp;amp;file=src/App.vue&amp;amp;hideExplorer=1&amp;amp;hideNavigation=1&amp;amp;view=preview&amp;amp;ctl=1" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vorms Example - Validate With Zod&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/vorms-validate-with-zod?embed=1&amp;amp;file=src/App.vue&amp;amp;hideExplorer=1&amp;amp;hideNavigation=1&amp;amp;view=preview&amp;amp;ctl=1" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks
&lt;/h2&gt;

&lt;p&gt;Vorms are heavily inspired by the following awesome projects.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jaredpalmer/formik" rel="noopener noreferrer"&gt;Formik&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/react-hook-form/react-hook-form" rel="noopener noreferrer"&gt;React Hook Form&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/logaretm/vee-validate" rel="noopener noreferrer"&gt;VeeValidate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Onwards and upwards
&lt;/h2&gt;

&lt;p&gt;Vorms has been used in many projects, but it is also a very new library, it will definitely have a lot of improvements and enhancements, I will continue to improve it, and any great ideas are also welcome to contribute.&lt;/p&gt;

&lt;p&gt;If you like what you see or you are interested and want to use Vorms in your own projects, please like us on &lt;a href="https://github.com/Mini-ghost/vorms" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading, hope this library could helps you. 💚&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
