Events and Forms
By Syncfusion®, Inc. · Last updated
v-on and @, method and inline handlers, $event, key aliases, system keys, .exact and event modifiers, then v-model on every control, value bindings, .lazy, .number and .trim, submit and reset, validation rules, error messages, accessible errors with useId() and validation libraries.
Events
- An event = something that happens on the page: a click, a key press, a mouse move.
v-onlistens for an event and runs your code when it happens.- Its short form is
@.v-on:clickand@clickare the same. - Your code usually changes state. Vue then updates the screen.
Simple lesson: @event="code" runs code when the event happens.
A Real-World Example
- Meera's counter has buttons for each dish.
- Each button adds a different number of plates.
- One method handles all buttons. Each button passes its own numbers.
What You Will Learn
- How to write inline handlers and method handlers, with arguments and
$event. - How to listen to mouse and keyboard events, key aliases and system keys.
- How event modifiers like
.stop,.preventand.oncework. - How
v-modellinks a form control and a ref both ways. - How to use
v-modelon every kind of control, with value bindings. - The
.lazy,.numberand.trimmodifiers. - How to submit and reset a form without a page reload.
- How to validate input and turn off the submit button.
- How to make errors clear for screen readers.
Inline and Method Handlers
- Inline handler = a short piece of code:
@click="count++". - Method handler = the name of a function:
@click="addOrder". - A method handler gets the event object as its first argument.
- Event object = details about the event, such as which element was clicked.
Arguments and $event
- Call the method with arguments:
@click="add(2)". - Then the event object is not passed by itself.
- Need both? Pass
$eventas an argument:@click="add(2, $event)". - You can also run two things:
@click="one(); two()".
Simple lesson: pass arguments in brackets. Add $event when you also need the event.
Name handlers after what they do, such as addOrder or openMenu, not after the event, such as onClick. The template then reads like a sentence.
Mouse and Keyboard Events
- Common mouse events:
click,dblclick,mouseenter,mouseleave,contextmenu. - Common keyboard events:
keydownandkeyup. - Key alias = a modifier that picks one key:
@keyup.enter. - Vue has aliases for
.enter,.tab,.delete,.esc,.space,.up,.down,.leftand.right. - You can also use any key name in kebab-case, such as
.page-down.
System Keys and .exact
- System keys =
.ctrl,.alt,.shiftand.meta(⌘ on Mac, ⊞ on Windows). @click.ctrlruns only if Ctrl is held during the click.@click.ctrlstill runs if Shift is held too..exactmeans "these keys and no others".@click.exact= no system key at all.
console is one of the safe globals a template may use, so the handlers above can log straight from the template. In bigger components, call a script function instead. It is easier to read and test.
Simple lesson: add .enter, .esc and friends for keys, and .ctrl or .exact for system keys.
Event Modifiers
- Event modifier = a dot word that changes how the event behaves.
.stop= stop the event from reaching parent elements. Same asevent.stopPropagation()..prevent= stop the browser's default action, like reloading on a form submit..self= run only if this exact element was clicked, not a child..capture= run on the way down, before the children..once= run one time only..passive= tell the browser you will not callpreventDefault. It makes scrolling smoother.
Animation: a click on a button inside a card inside the page. The event travels down in the capture phase, reaches the button, then bubbles up to the card and the page. With .stop on the button, it stops at the button
page (div)
card (div)
button
1. capture: down to the target 2. target: the button's handler 3. bubble: up to card, then page
Events go down (capture), hit the target, then bubble up. .stop ends the trip.
- What happened: "Like" logged twice, because the click bubbled to the card.
- "Save" logged once, because
.stopstopped it. - "Send" did not reload the page, because of
.prevent.
Without .prevent, a form submit reloads the page and you lose all your state. Always write @submit.prevent on Vue forms.
Chaining Modifiers
- You can chain modifiers:
@click.stop.prevent. - Order matters.
@click.prevent.selfprevents every click.@click.self.preventprevents only clicks on the element itself. - Do not use
.passiveand.preventtogether. The browser ignores.preventand warns.
Mouse Button Modifiers
.left,.rightand.middlepick a mouse button.@click.rightdoes not exist as a normal click. Use@contextmenuor@mouseup.right.- Add
.preventto stop the browser's own right-click menu.
Simple lesson: modifiers change how an event behaves. .prevent and .stop are the ones you will use most.
Forms in Vue
- Forms collect data: names, phone numbers, choices.
- Without Vue, you read each box by hand when the form is sent.
v-modellinks a form control and a ref both ways.- Two-way binding = typing changes the ref, and changing the ref changes the box.
v-modelignoresvalue,checkedandselectedwritten in the HTML. The ref is the only source of the start value.- For languages typed with an input method (IME), the ref updates when a word is finished, not on every key.
Simple lesson: v-model keeps a form control and your state the same, both ways.
In Practice: a Booking Form
- Meera takes table bookings online.
- She needs a name, the number of guests and a time.
- The summary below the form must update while people type.
How v-model Works
v-model="name"on a text box does two jobs:- it sets the box's
valuefromname - it updates
nameon everyinputevent
- it sets the box's
- It is short for
:value="name" @input="name = $event.target.value".
Animation: typing in the input sends the text to the ref through the input event, and changing the ref sends the value back to the input through the value binding
input box Asha Ravi
const name = ref("") "Asha" "Ravi"
@input :value
You type "Asha": the ref changes. The code sets "Ravi": the box changes.
v-model is a value binding plus an input listener.
Simple lesson: v-model = :value + @input, written once.
v-model on Every Control
- Text box and text area: binds the text.
- One checkbox: binds
trueorfalse. - Many checkboxes with one array: the array holds the
valueof each ticked box. - Radio buttons: binds the
valueof the chosen one. - Select: binds the chosen option. Add
multipleto bind an array.
v-model ignores the value, checked and selected attributes written in the HTML. The ref is the one source of truth. Set the starting value in the script.
Value Bindings
- By default a checkbox gives
trueorfalse, and a radio or option gives its text. true-valueandfalse-valuechange what one checkbox gives.:valuegives any JavaScript value, such as a number or an object.
Simple lesson: use :value, true-value and false-value when you need more than text.
Modifiers
.lazy= update onchange(when you leave the box), not on every key..number= turn the text into a number. Text that is not a number stays text.- On
<input type="number">, Vue applies.numberfor you. .trim= remove spaces at the start and the end.
- What happened: the city updated only after you left the box.
plates + 1did maths, not text joining.- The coupon lost its outer spaces.
Simple lesson: .lazy waits, .number makes numbers, .trim cuts spaces.
.number gives back the text when it cannot read a number, such as an empty box. Check with typeof or validation before doing maths with it.
Submitting and Resetting
- Listen with
@submit.preventon the<form>, so the page does not reload. - Read the refs. They already hold every value.
- To reset, put the starting values back into the refs.
- A
reactiveobject is handy for many fields. Reset it withObject.assign.
Simple lesson: @submit.prevent, read the state, then reset it.
Validation
- Validation = checking input before you accept it.
Common rules:
- required: not empty
- length: at least or at most some letters
- pattern: matches a shape, such as 10 digits
- numeric: a number in a range
- custom: any rule you write, such as "not on Monday"
- Keep the errors in a
computed. They update while people type. - Turn the submit button off while there are errors.
Show an error only after the person has touched a field, or tried to submit. Red text on an empty form before anyone types feels unfriendly. Keep a touched flag per field, set on @blur.
Accessible Errors
- A screen reader must know a field is wrong and why.
aria-invalid="true"marks the field as wrong.aria-describedby="id"links the field to its error text.- Ids must be unique on the page.
useId()(Vue 3.5) makes one for you.
Validation Libraries
- Big forms use a library, so you do not write every rule by hand.
- VeeValidate = a Vue form library: fields, rules, touched state and errors.
- Zod = describes the shape of data once, then checks it.
- They are installed with npm in a real project. This course writes rules by hand to show the idea.
// A real project: npm install vee-validate zod @vee-validate/zod
import { useForm } from "vee-validate";
import { toTypedSchema } from "@vee-validate/zod";
import { z } from "zod";
const { errors, defineField } = useForm({
validationSchema: toTypedSchema(
z.object({ phone: z.string().regex(/^\d{10}$/, "Enter a 10-digit phone number.") }),
),
});
Simple lesson: keep errors in a computed, disable submit while there are errors, and link each error to its field.
TL;DR
@click="code"= short forv-on:click. Runs code on a click.$event= the event object, when you also pass arguments.- Key alias =
@keyup.enter,.esc,.space,.up... .stop= stop bubbling to parents..prevent= stop the browser's default action.v-model= two-way binding::valueplus@input..lazy/.number/.trim= on change / as a number / no outer spaces.- Validation = errors in a
computed,:disabled="!valid". - Accessible errors =
aria-invalid,aria-describedby,useId().
Common mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
@click="add()" then reading the event | The event is still passed | Pass $event: add($event) | The event argument is undefined |
Form without .prevent | Vue stops the reload | Write @submit.prevent | The page reloads and state is lost |
| Inner button triggers the card | Clicks stay on the button | Add .stop on the inner button | Two handlers run |
@click.ctrl fires with Ctrl+Shift | It means Ctrl only | Add .exact | The handler runs on extra key combos |
value="..." with v-model | The HTML value is the start value | Set the start value in the ref | The attribute is ignored |
No .number | A number input gives a number | Add .number | 2 + 1 becomes "21" |
| Checkboxes with a string ref | Many boxes fill a string | Use an array ref | Only true or false is stored |
No .prevent on submit | Vue stops the reload | @submit.prevent | The page reloads and the form clears |
| Errors shown before typing | Show every error at once | Wait for blur or a submit try | An unfriendly wall of red |
Check Yourself
Exercises
What to Remember
@eventlistens. Use a method name, or a call with arguments.- Add
$eventwhen you pass arguments and still need the event. - Key aliases and system keys pick exact keys.
.exactrules out the rest. v-modelbinds a control and a ref both ways.- Many checkboxes need an array. Use
:valuefor non-text values. .numberfor numbers,.trimfor clean text,.lazyto wait for change.
Next: Components and Single-File Components