Introduction
This documentation is made to support the Vue Flow Form open-source project - to help users and to encourage contributors. Documentation includes the latest project info, examples, and how-to's.
Vue Flow Form is a form generator Vue component, built as a lightweight solution with minimum dependencies. Create reactive, dynamic, and highly extensible forms with various field types, step-by-step interface, and conditional-logic. You can customize the appearance with slots and CSS variables.
Installation
Creating a form
- To create a new form, import the necessary components and classes into your app, in a way that depends on the installation method and version of Vue Flow Form.
- Add the component to your template and register it either locally or globally.
- Define the form steps by passing the question options into
QuestionModel
class instances. Create as manyQuestionModel
instances as you like for your project by adding them inside thequestions
array in thedata
function. - Include the pre-built theme file or your own custom theme into your application #↓
- Add language model as
language
prop (optional) and define it by creating a new instance ofLanguageModel
and setting its properties. #↓ - Add
submit
and/orcomplete
event listeners if you want to submit data to the backend.
When using npm
- Import the
FlowForm
component itself, theQuestionModel
class andQuestionType
enum. If you're going to use theMultipleChoice
orDropdown
field type, import theChoiceOption
class// import from npm package import { FlowForm, QuestionModel, QuestionType, ChoiceOption, LanguageModel, MatrixRow, MatrixColumn } from '@ditdot-dev/vue-flow-form';
// import from npm package import FlowForm, { QuestionModel, QuestionType, ChoiceOption, LanguageModel } from '@ditdot-dev/vue-flow-form@1.1.7';
- Add
FlowForm
component with the question list asquestions
prop - Define questions in the
questions
array - Import base CSS and optional theme CSS #↓
When using CDN
- Vue Flow Form requires:
- at least Vue version 3.x for Vue Flow Form v2.x or later
- at least Vue version 2.6.x for Vue Flow Form v1.1.7
- You can use the latest version, or any specific version including the Vue 2 compatible build:
<script src="https://unpkg.com/@ditdot-dev/vue-flow-form@2.3.2"></script>
<script src="https://unpkg.com/@ditdot-dev/vue-flow-form@1.1.7"></script>
- Usage with plain JavaScript via CDN:
- Import Vue.js, FlowForm in either the head or before closing the body of your HTML document
- Import base CSS and theme CSS (optional) in the head of your HTML document #↓
- Create new Vue instance in your app.js and add the
questions
array withQuestionModel
instances - Make sure to register all components locally when using Vue 3
Question types
- Text -
QuestionType.Text
- LongText (Textarea) -
QuestionType.LongText
- Number -
QuestionType.Number
- Email -
QuestionType.Email
- Phone -
QuestionType.Phone
- URL -
QuestionType.Url
- Password -
QuestionType.Password
- Date -
QuestionType.Date
- A native input type="date" datepicker
- Browsers that don't natively support it (like Safari) will fall back to a text input. You can use the
placeholder
attribute to describe the expected date format - Alternatively, you can create a date input field by adding
mask
andplaceholder
attributes toQuestionType.Phone
import { MaskPresets } from '@ditdot-dev/vue-flow-form'; new QuestionModel({ type: QuestionType.Phone, // use one of the MaskPresets constants or create your own - https://vuejs-tips.github.io/vue-the-mask/#tokens mask: MaskPresets.Date, placeholder: 'yyyy-mm-dd' // ... });
- Dropdown (Select) -
QuestionType.Dropdown
- MultipleChoice -
QuestionType.MultipleChoice
- MultiplePictureChoice -
QuestionType.MultiplePictureChoice
- OpinionScale -
QuestionType.OpinionScale
- IconRate -
QuestionType.IconRate
- File -
QuestionType.File
- Matrix -
QuestionType.Matrix
- SectionBreak -
QuestionType.SectionBreak
Defining questions
- To define a question, create a new instance of
QuestionModel
and pass in the optionsnew QuestionModel({ id: 'path_b', tagline: 'Path B', title: 'Hmm, are you sure?', subtitle: 'Path A sounds like a winner! 😉', type: QuestionType.MultipleChoice, multiple: false, required: true, options: [ new ChoiceOption({ label: 'Ok, let\'s go with A', value: 'path_a' }), new ChoiceOption({ label: 'Yes, finish the survey' }) ], jump: { path_a: 'path_a' } })
Global options
-
type
- (one ofQuestionType
constants above) -
id
- ID of the question (optional but necessary when usingjump
) -
title
- main title -
tagline
- text above question (optional) -
subtitle
- text below question (optional) -
description
- helper text below main content (optional) -
descriptionLink
- add links below main content (optional):descriptionLink: [ new LinkOption({ url: 'https://www.example.com', text: 'Example link', // optional, default is link url target: '_self' // optional, default is '_blank' }) ]
- if description text is defined, links will be added to the end of the description text
-
required
- is field required or not (true/false - default is false)- turn on/off the required asterisk indicator next to the question in vue-flow-form/src/assets/css/common.css:
.f-required { display: inline; /* or display: none; to turn off */ }
- turn on/off the required asterisk indicator next to the question in vue-flow-form/src/assets/css/common.css:
-
answer
- holds the user's answer after replying to a question. This can for example be used to pre-fill the answer to any of the questions. -
jump
- define which question to jump to after answering (function or object)- function: it will get the question model as the only parameter and must return the ID to jump to
-
object: must define object with possible answer values and jump IDs, eg.:
{ a: 'jump_a', b: 'jump_b', c: '_submit', _other: 'jump_other' }
- Object key
_other
will be used when no other keys match the answer. Object value_submit
will jump to form submit button
-
progressbar
You can disable the progress bar (UX recommendation if you have many logic jumps) by passingfalse
to theprogressbar
prop on the FlowForm component instance:<flow-form v-bind:progressbar="false"> <!-- ... --> </flow-form>
-
navigation
You can disable the footer backward/forward navigation and Shift + Tab backward navigation by passingfalse
to thenavigation
prop on the FlowForm component instance:<flow-form v-bind:navigation="false"> <!-- ... --> </flow-form>
-
timer
Timer option is available by passingtrue
to thetimer
prop on the FlowForm component instance. By default, the timer starts on the first step and ends on submit. Start and stop steps can be changed by passing the question ID to thetimerStartStep
and/ortimerStopStep
props:<flow-form v-bind:timer="true" timer-start-step="id_1" timer-stop-step="id_2"> <!-- ... --> </flow-form>
Question specific options
-
content
- used only with SectionBreak (optional) -
options
-ChoiceOption
array (used only with Dropdown and MultipleChoice)-
ChoiceOption
must have alabel
defined (this is what will be shown to the user) - if
value
is not defined,label
will be used
-
-
inline
- displays the field next to the question, used only with Dropdown (true/false - default is false) -
placeholder
- define custom placeholder for the input fields- if not defined, the default value from LanguageModel will be used
-
mask
- input mask, used with Text, Email, Phone, Password and Number (optional)- vue-the-mask is used to provide the masked input option
-
maxLength
- defines the maximum number of characters the user can enter into a Text, LongText, Number, Url, Phone, Password, Email or Date field -
min
andmax
- specifies the minimum and maximum value, when used with Date (in "yyyy-mm-dd" format) or Number. Defines the minimum and maximum number of uploaded files, when used with File (only whenmultiple
is set totrue
).max
is also used to set the number of options for the OpinionScale and IconRate questions -
labelLeft
andlabelRight
- used only with OpinionScale to add labels to the left and right of the number scale -
helpText
- help text, used only with LongText and MultipleChoice (optional)- if not defined, the default values from LanguageModel will be used
-
helpTextShow
- shows help text, used with LongText and MultipleChoice (true/false - default is true) -
multiple
- when used with MultipleChoice, MultiplePictureChoice or Matrix, defines if multiple answers can be chosen (true/false - default is false). Used with File, allows more than one file to be selected (true/false - default is false) -
allowOther
- used only with MultipleChoice, adds custom text field to the MultipleChoice selection (true/false - default is false) -
nextStepOnAnswer
- used with MultipleChoice and MultiplePictureChoice (only whenmultiple
is set tofalse
), OpinionScale and IconRate; takes you to the next step after selecting an option (true/false - default is false) -
imageSrc
- used only with MultiplePictureChoice, adds image to the MultiplePictureChoice option -
imageAlt
- used only with MultiplePictureChoice, adds alt text to the MultiplePictureChoice option image -
accept
- used only with File, defines the file types the input should accept - MDN documentation -
maxSize
- used only with File, defines the maximum overall size of all uploaded files, in bytes -
rows
- add question rows to Matrix:rows: [ new MatrixRow({ id: 'experience', label: 'Rate your overall experience with our product' }), new MatrixRow({ id: 'documentation', label: 'Rate your overall experience with our documentation' }) ]
-
columns
- add column options to Matrix:columns: [ new MatrixColumn({ value: '1', label: 'Very satisfied' }), new MatrixColumn({ value: '2', label: 'Satisfied' }) ]
For additional guidance, check the Questionnaire or other examples to see all question types defined.
Questions as components
- This feature allows dynamic questions and Vue's conditional rendering, just make sure to define a unique ID for each question. Example usage:
<template> <flow-form> <question id="name" type="text" title="Hello, what is your name?" v-model="name"></question> <question id="age" type="number" title="What is your age?" v-model="age"></question> <!-- name and age are stored in the FlowForm component's data and can be used in the following question --> <question v-if="age < 18" id="ageLimit" type="sectionbreak" title="Sorry, you are under 18"></question> <question v-else type="sectionbreak" id="greeting" :title="'Nice to meet you, ' + name + '. Welcome to our site!'"></question> </flow-form> </template> <script> import FlowForm from '../../src/components/FlowForm.vue' import Question from '../../src/components/Question.vue' // If using the npm package, use the following line instead of the ones above. // import { FlowForm, Question } from '@ditdot-dev/vue-flow-form' export default { name: 'example', components: { FlowForm, Question }, data() { return { name: '', age: '' } } } </script>
- When using CDN, make sure to register the Question component locally:
export default { name: 'example', components: { question: VueFlowForm.Question }, ... }
export default { name: 'example', components: { question: FlowForm.Question }, ... }
Public API functions
-
reset
- resets all the answers and returns to the first question. -
goToQuestion
,goToPreviousQuestion
,goToNextQuestion
- API functions which let you go to a specific question. Note: Allowed only if application logic allows it, to avoid skipping required questions that weren't already answered. - You can use API function by storing a ref to Flow Form in your parent component and calling it, eg.:
mounted() { this.$refs.flowform.goToQuestion(3) // You can also jump by question ID: // this.$refs.flowform.goToQuestion('question_id') }
FlowForm component events
-
complete
- emitted whenever the "completed" status changes, the first parameter is the status, the second is the question list, eg.:function onComplete(completed, questionList) { // Handle status change. }
- If the user completes the form, then goes back and changes any of the answers to make them invalid, this event will again be called with
false
as the first parameter, so make sure to handle this correctly in your app. -
submit
- when the default "submit" button is clicked - if you override the defaultcompleteButton
slot, this event won't be called (example in Example.vue)function onSubmit(questionList) { // Handle submit event. }
-
answer
- gets fired after a question is answeredfunction onAnswer(questionAnswered) { // Handle answer event. }
-
step
- gets fired when a new step is displayedfunction onStep(activeQuestionId, activeQuestion) { // Handle step event. }
FlowForm component slots
-
complete
- Complete/submit screen content- This is the content of your custom complete screen, by default the
thankYouText
language string is used, but you can customize this screen to look like you want
- This is the content of your custom complete screen, by default the
-
completeButton
- Complete/submit screen button- If you override the button, the
complete
event will not be called so you'll need to handle the buttononClick
event manually
- If you override the button, the
Submitting data
- the
submit
event emits an event with the question list as the only parameter. You can then send the data to your backend usingfetch
API or something likeAxios
. If you've overridden the defaultcompleteButton
slot, implement thecomplete
event to know when the user is on the complete screen and handle the rest manually. - when your form contains one or more
QuestionType.File
question types, make sure you're using theFormData
interface to correctly send all of the gathered data to your back-end, eg.:function onSubmit(questionList) { // Handle submit event. const formData = new FormData() questionList.forEach(question => { formData.append(question.id, question.answer) }) fetch(url, { method: 'POST', body: data }) }
Theming
Using a pre-built theme
- Vue Flow Form comes with several out-of-the box theme CSS files. Theme files include all common color and typography styles.
- When using npm or CDN, just import one of the available themes together with the base CSS file
- CSS variables support for legacy browsers is included in the example project. If you need to support legacy browsers in your project when using the npm package, either create an alternate theme without using variables or use css-vars-ponyfill
- There are three pre-built themes:
- To use a theme when using the npm package, import it in your style block:
@import '~@ditdot-dev/vue-flow-form/dist/vue-flow-form.theme-[THEME NAME].css';
- When using the CDN version, reference the CSS using one of the CDN links above
- Dark mode support is enabled by using the
prefers-color-scheme
media query@media (prefers-color-scheme: dark) { /* dark mode styles go here */ }
Defining a custom theme
- Customize existing themes as you like or create your own. The easiest way to create a new theme is to copy and change one of the pre-built theme CSS files from the src/assets/css/themes folder
- When using npm or CDN, customize/create the theme and import it into your app as you would do with the pre-built theme
- You can further customize other aspects of the app for your particular needs in the src/assets/css/common.css
Layout options
- Standalone (default) layout is suitable for a full-page display, or you can use a non-standalone layout - more suitable for integrating and embedding into your existing layout.
- To use Vue Flow Form as an integrated component embed it into an applicable HTML element and pass
false
to thestandalone
prop on the FlowForm component instance:<flow-form v-bind:standalone="false"> <!-- ... --> </flow-form>
Multilanguage Support
- To translate the form fields and values into your preferred language, create a language object and define language options
- Use the language object with the LanguageModel instance
// npm example import { FlowForm, QuestionModel, QuestionType, ChoiceOption, LanguageModel, MatrixRow, MatrixColumn } from '@ditdot-dev/vue-flow-form'; export default { name: 'example', components: { FlowForm }, data() { return { language: new LanguageModel({ continue: 'Fortsetzen', pressEnter: 'Drücken Sie ENTER', otherPrompt: 'Andere', submitText: 'Einreichen' // ... }) // ... } } }
// npm example import FlowForm, { QuestionModel, QuestionType, ChoiceOption, LanguageModel } from '@ditdot-dev/vue-flow-form@1.1.7'; export default { name: 'example', components: { FlowForm }, data() { return { language: new LanguageModel({ continue: 'Fortsetzen', pressEnter: 'Drücken Sie ENTER', otherPrompt: 'Andere', submitText: 'Einreichen' // ... }) // ... } } }
Source code and demo examples
- Questionnaire (default):
- example containing a sample questionnaire
- Live demo
- Quiz:
- example showing how the component can be used in a more advanced way
- this example shows the number of correctly answered questions after submitting the form, along with an accompanying message
- to view this quiz example, change the entry point in vue.config.js to
'examples/quiz/main.js'
- Live demo
- Support page:
- example of a support ticket form
- this example allows you to submit a support request or to check your existing ticket status
- to view this customer support example, change the entry point in vue.config.js to
'examples/support-page/main.js'
- Live demo
Files/folders
- CSS: src/assets/css
- Vue components: src/components, src/components/QuestionTypes
- Models: src/models
Demo project usage
Set corresponding JavaScript entry file in vue.config.js (examples in examples /example-name / Example.vue)
module.exports = {
publicPath: '',
pages: {
index: {
entry: 'examples/questionnaire/main.js', // Replace with your .js entry file path
template: 'public/index.html',
filename: 'index.html'
}
}
}
How to contribute:
Pull requests and potential features are welcome.
# clone repo
$ git clone https://github.com/ditdot-dev/vue-flow-form.git
# create a new branch
$ git checkout -b new_branch_name
# make changes, test and submit pull request with description of changes
If you think you found a bug, perform the Issues search to see if the problem has already been reported. If you're unable to find an issue addressing it, create a new issue that thoroughly explains the problem, with clear steps to reproduce.
Made with Vue.js