Handling forms in Vue with FormKit

    Nefe James

    Nefe is a frontend developer who enjoys learning new things and sharing his knowledge with others.

    Published on

    April 19, 2022
    Handling forms in Vue with FormKit


    Forms are an integral part of web development because they are one of the most common ways people interact with the web.

    Most websites and web applications are not static, and users will often be required to input some data into a form and get some input in return.

    As developers, we will sometimes need to add forms to our applications. However, handling and validating forms can quickly become tedious and repetitive.

    In this article, we will learn about FormKit, its features, and how it enables us to handle forms.

    What is FormKit?

    FormKit is a new open-source form authoring framework created by Justin Schroeder, the author of Vue Formulate. It is currently in public beta. It supports handling forms in Vue 3 and works with Nuxt 3 out of the box.

    FormKit is the one-stop solution for high-end forms in Vue.js applications. It includes everything needed — labels, helper text, theming support, validation, form generation from JSON, accessibility, internationalization, and more!

    FormKit was not just created to provide support for Vue 3, but also to address Vue Formulate’s limitations: To do that, it comes packed with the following features and more:

    • High performance at scale
    • TypeScript support
    • Flexible DOM structure
    • Structured form data
    • Input masks
    • Async validation rules
    • Better utility class support
    • New and improved documentation
    • Improved accessibility


    Knowledge of Vue is required for this article.

    Getting started

    We need to create a new Vue application to get started.

    First, run the command below to initialize a new Vue application:

    npm init vue@latest

    The image below shows the options Vue’s interactive CLI provides for us to choose from. For this article, we set the options to “No” however, in a real-world project, we are free to choose the settings that best fit the needs of our application.

    Display of options Vue’s interactive CLI provides for us to choose from

    Next, run the following commands in sequence to install the dependencies and start the dev server:

    cd <your-project-name>
    npm install
    npm run dev

    Run the command below to install FormKit:

    npm install @formkit/vue

    Next, we set up and configure FormKit into our application. Update the main.js file with the code below:

    import { createApp } from 'vue'
    import App from 'App.vue'
    import { plugin, defaultConfig } from '@formkit/vue'
    createApp(App).use(plugin, defaultConfig).mount('#app')

    With that, we can use `FormKit` in our Vue application. The `defaultConfig` includes all of FormKit's inputs, validation rules, and the English language.

    The FormKit component

    FormKit provides a FormKit component we can use to create forms. It works the same way we expect a <input> tag to work.

    FormKit is a supercharged version of HTML’s input element. It accepts the same attributes as the HTML input and extends the basic functionality with features such as adding labels, help text, validation, error messages, and much more.

    We only have to learn the FormKit component when working with FormKit. As of this writing, FormKit renders 24 input types.

    Let’s create a text input component with FormKit to see how it works. Update the App.vue file with the code below:

      <FormKit type="text" placeholder="What is your name" label="Name" />

    We pass the text, placeholder. and label props to FormKit.

    The code above will render the following input in the DOM. We can see that we get a regular HTML input in the end.

    Image displaying the regular HTML input

    The image below shows the form we created.

    Text input field titled Name with microcopy saying What is your name

    Creating a basic form with FormKit

    This section will teach the reader how to use FormKit and integrate it into their forms.

    FormKit supports different types of input fields with its custom FormKit element. This section will also explain how that works.

    Creating form fields with FormKit is straightforward. Now that we know how it works let's create a basic form.

    Update the App.vue file with the code below:

      <FormKit type="form">
          label="New password"
          label="Password confirmation"

    Here, we create four input fields where users can put their name, email, and password details. We wrap the input fields in a parent FormKit component and set its type to form.  

    The code above produces the following form:

    Form with four text input fields: Name, email, new password, and password confirmation

    Notice that we have one here even though we did not add a submit button in our code. FormKit automatically adds the submit button for us when we add the parent FormKit wrapper.

    The default value of the button is Submit, but we can change that using the submit-label prop.

      <FormKit type="form" submit-label="Register">
      //input fields below 


    FormKit provides a developer-friendly API for handling validation.

    We can validate input fields by passing validation rules to their validation prop. Once again, FormKit has abstracted the complexity for us by providing pre-written validation rules for us. As of this writing, there are 22 pre-written rules.

    Not only is the validation API wonderful to work with, but FormKit also handles the displaying of errors for us. We don’t have to track the errors for each input field and conditionally display them; FormKit does that for us.

    Let’s add validation rules to our form.

      <FormKit type="form" submit-label="Register">
        <FormKit name="name" validation="required" />
        <FormKit name="email" validation="required|email" />
        <FormKit name="password" validation="required|length:6" />
        <FormKit name="password_confirm" validation="required|confirm" />

    We declare the validation rules directly on our inputs. These are the rules we set up:

    • The name input is required.
    • The email is required, and it has to be a valid email address.
    • The password is required, and it cannot be less than six characters.
    • The confirm password input is required. and its value must match that of the password input.

    This pattern of form validation makes the rules easier to read.

    Form with 4 required text input fields: Name, email, new password, and password confirmation that closes with a Register call-to-action button

    Our form looks horrible because we have not worked on the styling yet. We will learn how to style FormKit forms later in the article.

    Form submission

    The parent FormKit component tracks the validation state of its children's input fields and ensures they are all valid before submitting. It also disables all inputs while the submission is pending.

      <FormKit type="form" submit-label="Register" @submit="submitHandler">
        <FormKit name="name" validation="required" />
        <FormKit name="email" validation="required|email" />
        <FormKit name="password" validation="required|length:6" />
        <FormKit name="password_confirm" validation="required|confirm" />
      function submitHandler(values) {
        //do something with the form data
    // the console.log output
    { name: "John Doe", email: "", password: "secret", password_confirm: "secret" }

    We create a submitHandler function which takes in the form data. Here, we are logging the data to the console, but in a real-world application, we would want to do something else

    We pass submitHandler to FormKit's @submit event prop. FormKit passes the data to submitHandler.

    Styling FormKit forms

    FormKit is a feature-packed library, but it doesn’t stop there: it also comes with an optional styling theme called Genesis.

    We have to first install the @formkit/themes package before we can use Genesis.

    npm install @formkit/themes

    Next, we import the Genesis theme into our main.js file,

    import { createApp } from "vue";
    import App from "./App.vue";
    import { plugin, defaultConfig } from "@formkit/vue";
    import "@formkit/themes/genesis";
    createApp(App).use(plugin, defaultConfig).mount("#app");

    With that, our form has an entirely different and better appearance.

    Image of the previous 4-text input field form with new styling thanks to the Genesis theme

    Besides styling the form, the Genesis theme also adds a loading spinner to the button while the submission is pending.

    Custom classes

    We are not restricted to the Genesis theme and can add custom classes to change the styling of the form.

      <FormKit type="form" submit-label="Register" @submit="submitHandler">
            label: 'name-label',
            label: 'email-label',
        <FormKit name="password" />
        <FormKit name="password_confirm" />
      .name-label {
        color: green;
      .email-label {
        color: red;
      [data-type="submit"] .formkit-input {
        background: red !important;

    FormKit accepts a classes prop where we can target the aspect of the field we want to style.

    Here, we target the name and input field labels and give them the name-label and email-label classes, respectively.

    In the style tag, we change the color of the name’s label to green and the email’s to red.

    We can also track the selectors FormKit used from our browser's devtools and update elements with those selectors, like the button.  

    At times, we may need to add the !important rule to handle conflicts between our custom styles and those in the Genesis theme.

    The image below shows the styles we added to the form.

    Form with 4 text input fields in the applied styling we did using custom classes

    Schema form generation

    Another great feature of FormKit is schema generation, which can be a low-effort method of creating form fields.

    A schema in FormKit is an array of objects, where each object is an HTML element.

    Let’s see how this works.

      <FormKit type="form">
        <FormKitSchema :schema="schema" />
    <script setup>
      import { FormKitSchema } from "@formkit/vue";
      const schema = [
          $formkit: "text",
          name: "name",
          label: "Full Name",
          placeholder: "Enter your name",
          $formkit: "email",
          name: "email",
          label: "Email Address",
          placeholder: "Enter your email",

    Here, we define a schema array that contains the different input fields we want to generate. Next, we import the FormKitSchema component and pass the schema array to it as a prop.


    FormKit has several selling points. It comes packed with several great features, a developer-friendly API, and a comprehensive documentation with several examples and covers multiple use cases.

    The amazing thing is that as of this writing, it's still in beta. With more updates and features added in the future, this is definitely a library to watch out for.

    Overall, FormKit is an excellent library that does an excellent job of handling forms.

    Data-rich bug reports loved by everyone

    Get visual proof, steps to reproduce and technical logs with one click

    Make bug reporting 50% faster and 100% less painful

    Rating LogosStars
    Category leader

    Liked the article? Spread the word

    Put your knowledge to practice

    Try Bird on your next bug - you’ll love it

    “Game changer”

    Julie, Head of QA


    Overall rating: 4.7/5

    Try Bird later, from your desktop