DEV Community

Cover image for Build a Multi-Step Form in Vue in 5 minutes.
Andrew Boyd
Andrew Boyd

Posted on

Build a Multi-Step Form in Vue in 5 minutes.

Few interactions on the web cause as much displeasure for a user as being confronted with a large, intimidating form. Multi-step forms can alleviate this pain by breaking a large form into smaller, approachable steps — but they can also be quite complicated to build.

In this guide, we'll walk through building a multi-step form with FormKit (a free and open-source form building framework) and see how we can provide an elevated user experience with minimal code. We'll be done in approximately 5 minutes. Let's get started!

Not familiar with FormKit? It's a free and open-source framework for building forms in Vue and you can learn more about it here.

Installation

To get started we need to install FormKit, its supporting default theme, and the FormKit Multi-Step plugin into our project:

npm install @formkit/vue @formkit/addons @formkit/themes
Enter fullscreen mode Exit fullscreen mode

Then we add FormKit to our Vue app, add the Multi-Step Plugin to our FormKit config, and ensure that we're including the necessary styles:

// main.js
import { createApp } from 'vue'
import App from 'App.vue'
// FormKit imports
import { plugin as formKitPlugin, defaultConfig } from '@formkit/vue'
import { createMultiStepPlugin } from '@formkit/addons'
import '@formkit/themes/genesis'
import '@formkit/addons/css/multistep'

createApp(App)
  .use(formKitPlugin, defaultConfig({
    plugins: [createMultiStepPlugin()]
  }))
  .mount('#app')
Enter fullscreen mode Exit fullscreen mode

Usage

Out-of-the-box, FormKit ships with every native HTML input available to you. Things like text, select, checkbox, etc.

createMultiStepPlugin registers two brand-new input types for you to use with FormKit — in exactly the same way you use any other input type.

  • multi-step: The wrapping group for the entire multi-step input.
  • step: The wrapping group for a given step within your multi-step input.

Using these inputs together is as simple as wrapping any markup you want to have present within a step in a multi-step form:

<FormKit type="multi-step">
  <FormKit type="step" name="stepOne">
    <!-- content for stepOne goes here! -->
  </FormKit>
</FormKit>
Enter fullscreen mode Exit fullscreen mode

So — let's build a quick form for users who want to submit a talk to our upcoming fake conference, VueUniverse.

We'll want to:

  • Collect some contact information for the user.
  • Get a brief overview of the talk the user wants to give.
  • Ask the user how they heard about VueUniverse.

Those sound like good groupings for our steps — so let's get started:

<FormKit type="form">
  <FormKit type="multi-step">
    <FormKit type="step" name="contactInformation">
      <!-- collect name, email, and company info -->
      <FormKit 
        type="text" 
        label="Your Name" 
        validation="required"
      />
      <FormKit 
        type="email" 
        label="Your Email" 
        validation="required|email" 
      />
      <FormKit 
        type="text" 
        label="Your Company (optional)"
        help="Are speaking on behalf of an organization?"
      />
    </FormKit>

    <FormKit type="step" name="talkDetails">
      <!-- Get talk title, brief, and track -->
      <FormKit 
        type="text" 
        label="Talk Title" 
        validation="required"
      />
      <FormKit 
        type="textarea" 
        label="Talk Brief" 
        validation="required|length:100"
        help="What is your talk about?"
      />
      <FormKit 
        type="radio" 
        label="Talk Track"
        help="Which track are you submitting for?"
        :options="['Development', 'Testing', 'Leadership']"
      />
    </FormKit>

    <FormKit type="step" name="referral">
      <!-- Ask the user to share how they heard about us -->
      <h2>Thank you for taking the time to submit your talk</h2>
      <p>If you don't mind we'd love to know how you heard about VueUniverse.</p>
      <FormKit 
        type="radio" 
        label="How did you hear about VueUniverse?" 
        :options="['Online Ad', 'Friend or Coworker', 'Search Results', 'Other']"
      />
    </FormKit>
  </FormKit>
</FormKit>
Enter fullscreen mode Exit fullscreen mode

And there we go! One component, FormKit, with a consistent API and we've got ourselves a working multi-step form with validation!

(for the best experience open this example in a new tab)

That's great! But there's two things we can change to make it better.

  • Since we're using the multi-step input as our entire form experience it would be great to have the submit button be inside the last step rather than external to the multi-step input.
  • We're asking users to go through a set flow, so it would be great if our tabs indicated progress. Additionally it would be great if we prevented the user from navigating to the next step until the current step is completed.

Thankfully, these are both very easy changes to implement.

  • First we need to set :actions="false" on our wrapping form type FormKit component to disable the default submit button. Then, using the stepNext slot we can insert our own submit button inside the last step in our multi-step form.
  • Second, we need to use the tab-style="progress" and allow-incomplete="false" props to show progress-style tabs and prevent the user from freely navigating through steps until validation is passed.

Here are the relevant sections of our form with those changes implemented:

<!-- remove default actions on the form -->
<FormKit 
  type="form"
  :actions="false"
>
  <!-- Set new props on our multi-step -->
  <FormKit 
    type="multi-step"
    tab-style="progress"
    :allow-incomplete="false"
  >
    ...
    <!-- In our last step, add a submit button -->
    <FormKit type="step" name="referral">
      ...
      <template #stepNext>
        <FormKit type="submit" />
      </template>
    </FormKit>
  </FormKit>
</FormKit>
Enter fullscreen mode Exit fullscreen mode

And again, that's it! FormKit takes care of the rest for us. Here is our new and improved multi-step form experience after changing those 6 lines of code.

(for the best experience open this example in a new tab)

Best of all this form has accessible markup, built-in validation, and much more that we didn't have to worry about ourselves thanks to the underlying FormKit component architecture.

Conclusion

Quick, easy, powerful. Implementing a multi-step form in your project has never been simpler.

By leveraging FormKit in your Vue projects you can supercharge your form development and build rich and complex user-experiences in a fraction of the time — for free.

Developer after building a multi-step in 5 minutes

Want to learn more about FormKit and how it can help with form structure, validation, accessibility, and more?

Top comments (3)

Collapse
 
sadeghbarati profile image
Sadegh Barati

Thanks 🙏

Just a question

How to integrate Formkit Multi Step with URL query params?

and How to validate URL query params when user add a key that does not exist in form

It would be nice if you add this example

Collapse
 
andrewboyd profile image
Andrew Boyd • Edited

So with FormKit you can pass the value prop to your <FormKit type="form"> component and all of the values will be propagated to the nested inputs based on input name / grouping.

So for params, you would do some sort of setup work where you fetch the params from the url, and then re-assemble your data object that you want to provide to values. If a matching FormKit node does not exist in your form the that value will be ignored.

You can read more about form data population here: formkit.com/inputs/form#populating

Collapse
 
sucodelarangela profile image
Angela Caldas

Exactly what I was looking for, thanks a million for sharing!