Form Examples
Common patterns for using toasts with form validation and submission.
Basic Form Submission
Successful Submission
vue
<script setup>
const toast = useToast();
const form = ref({
name: "",
email: "",
});
async function handleSubmit() {
try {
await api.submitForm(form.value);
toast.success(
"Form Submitted",
"Your information has been saved successfully"
);
// Reset form
form.value = { name: "", email: "" };
} catch (error) {
toast.error("Submission Failed", error.message);
}
}
</script>
<template>
<form @submit.prevent="handleSubmit">
<input v-model="form.name" placeholder="Name" />
<input v-model="form.email" placeholder="Email" />
<button type="submit">Submit</button>
</form>
</template>
Validation Errors
vue
<script setup>
const toast = useToast();
function validateForm(form) {
const errors = [];
if (!form.email.includes("@")) {
errors.push("Invalid email address");
}
if (form.password.length < 8) {
errors.push("Password must be at least 8 characters");
}
if (errors.length > 0) {
toast.error("Validation Error", errors.join(". "));
return false;
}
return true;
}
async function handleSubmit() {
if (!validateForm(form.value)) {
return;
}
// Submit form...
}
</script>
File Upload Forms
Upload Progress
vue
<script setup>
const toast = useToast();
async function uploadFile(file) {
// Show initial upload toast
toast.info("Uploading...", file.name, {
showProgress: true,
duration: 10000,
});
try {
await api.upload(file, {
onProgress: (percent) => {
// Update progress if needed
},
});
toast.success("Upload Complete", `${file.name} uploaded successfully`);
} catch (error) {
toast.error("Upload Failed", error.message);
}
}
function handleFileChange(event) {
const files = Array.from(event.target.files);
files.forEach(uploadFile);
}
</script>
<template>
<input type="file" @change="handleFileChange" multiple />
</template>
Multiple File Upload
vue
<script setup>
const toast = useToast();
async function uploadMultipleFiles(files) {
const fileArray = Array.from(files);
let successful = 0;
let failed = 0;
toast.info("Uploading Files", `Processing ${fileArray.length} files...`, {
showProgress: true,
});
for (const file of fileArray) {
try {
await api.upload(file);
successful++;
} catch (error) {
failed++;
}
}
if (failed === 0) {
toast.success(
"All Files Uploaded",
`${successful} files uploaded successfully`
);
} else {
toast.warning(
"Upload Complete with Errors",
`${successful} succeeded, ${failed} failed`,
{
actions: [
{
label: "View Details",
onClick: () => showUploadDetails(),
},
{
label: "Retry Failed",
onClick: () => retryFailedUploads(),
},
],
}
);
}
}
</script>
File Size Error
vue
<script setup>
const toast = useToast();
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
function handleFileSelect(event) {
const file = event.target.files[0];
if (file.size > MAX_FILE_SIZE) {
toast.error("File Too Large", `${file.name} exceeds the 10MB limit`, {
actions: [
{
label: "Compress File",
onClick: () => openCompressor(file),
},
],
});
event.target.value = ""; // Clear input
return;
}
uploadFile(file);
}
</script>
Login/Authentication Forms
Successful Login
vue
<script setup>
const toast = useToast();
const router = useRouter();
async function handleLogin(credentials) {
try {
const user = await auth.login(credentials);
toast.success("Welcome Back!", `Logged in as ${user.name}`, {
avatar: {
type: "image",
src: user.avatar,
},
});
router.push("/dashboard");
} catch (error) {
toast.error("Login Failed", error.message);
}
}
</script>
Invalid Credentials
vue
<script setup>
const toast = useToast();
async function handleLogin(credentials) {
try {
await auth.login(credentials);
} catch (error) {
toast.error(
"Login Failed",
"Invalid email or password. Please try again.",
{
actions: [
{
label: "Forgot Password?",
onClick: () => navigateTo("/forgot-password"),
},
],
}
);
}
}
</script>
Two-Factor Authentication
vue
<script setup>
const toast = useToast();
async function sendVerificationCode(email) {
try {
await auth.send2FA(email);
toast.info(
"Verification Code Sent",
"Check your email for the 6-digit code",
{
icon: "i-lucide-mail",
showProgress: true,
duration: 8000,
}
);
} catch (error) {
toast.error("Failed to Send", error.message);
}
}
</script>
Registration Forms
Account Created
vue
<script setup>
const toast = useToast();
async function handleRegistration(userData) {
try {
await api.register(userData);
toast.success(
"Account Created!",
"Welcome to our platform. Please verify your email.",
{
actions: [
{
label: "Verify Email",
onClick: () => navigateTo("/verify-email"),
},
{
label: "Complete Profile",
onClick: () => navigateTo("/profile/edit"),
},
],
duration: 10000,
}
);
} catch (error) {
toast.error("Registration Failed", error.message);
}
}
</script>
Email Already Exists
vue
<script setup>
const toast = useToast();
async function checkEmail(email) {
const exists = await api.checkEmailExists(email);
if (exists) {
toast.warning("Email Already Registered", "This email is already in use", {
actions: [
{ label: "Login Instead", onClick: () => navigateTo("/login") },
{ label: "Forgot Password?", onClick: () => navigateTo("/forgot") },
],
});
return false;
}
return true;
}
</script>
Auto-Save Forms
Draft Saved
vue
<script setup>
const toast = useToast();
const content = ref("");
let saveTimeout = null;
watch(content, () => {
clearTimeout(saveTimeout);
saveTimeout = setTimeout(autoSave, 2000);
});
async function autoSave() {
try {
await api.saveDraft(content.value);
toast.success("Draft Saved", "Changes saved automatically", {
duration: 2000,
position: "bottom-right",
});
} catch (error) {
toast.error("Save Failed", "Could not save draft", {
duration: 3000,
});
}
}
</script>
Form Recovery
Unsaved Changes Warning
vue
<script setup>
const toast = useToast();
const hasUnsavedChanges = ref(true);
onBeforeRouteLeave((to, from, next) => {
if (hasUnsavedChanges.value) {
toast.warning(
"Unsaved Changes",
"You have unsaved changes. What would you like to do?",
{
duration: Infinity,
actions: [
{
label: "Save & Leave",
onClick: async () => {
await saveChanges();
next();
},
},
{
label: "Discard",
onClick: () => {
hasUnsavedChanges.value = false;
next();
},
},
{
label: "Stay",
onClick: () => {
toast.clear();
next(false);
},
},
],
}
);
next(false);
} else {
next();
}
});
</script>
