Vue
Vue.js is a progressive JavaScript framework for building user interfaces, designed to be approachable, versatile, and easy to integrate, with a focus on declarative rendering and component-based architecture.
Prerequisites
Before you begin, make sure you have:
- A Basestack Forms account
- A Vue.js project with a form component
Quick Setup Guide
Follow these steps to integrate Basestack Forms with your Vue.js application:
Choose your HTTP client
You can use any HTTP client library to send form data from your Vue component. Popular options include:
- Fetch API - Built into modern browsers, no installation needed
- Axios - Popular HTTP client with Vue-friendly features
- Any other HTTP client that supports POST requests
Include mode=rest in your endpoint URL query string to receive JSON responses. This allows you to handle the response and show success or error messages to users.
Implement form submission handler
Copy the example component below into your Vue project. The example demonstrates:
- Form state management using Vue's Composition API
- Form submission with Fetch API
- Basic error handling and success feedback
The example uses Vue 3's Composition API with reactive and toRefs. Adapt it to your Vue version and preferred API style.
<template>
<form @submit.prevent="onHandleSubmit">
<div>
<label for="name">Name</label>
<input
type="text"
v-model="form.name"
id="name"
placeholder="Enter your name"
name="name"
required
autocomplete="name"
aria-label="Name"
/>
</div>
<div>
<label for="email">Email</label>
<input
type="email"
v-model="form.email"
id="email"
name="email"
required
autocomplete="email"
aria-label="Email"
placeholder="Enter your email"
/>
</div>
<div>
<label for="message">Message</label>
<textarea
v-model="form.message"
id="message"
name="message"
required
aria-label="Message"
placeholder="Enter your message"
></textarea>
</div>
<button type="submit">Submit</button>
</form>
</template>
<script>
import { reactive, toRefs } from "vue";
export default {
setup() {
const form = reactive({
name: "",
email: "",
message: "",
});
const onHandleSubmit = async () => {
try {
const res = await fetch(
"https://forms-api.basestack.co/v1/s/[KEY]?mode=rest",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(form),
},
);
const data = await res.json();
if (data.code === 200) {
console.log("Form submitted successfully");
}
} catch (error) {
console.log("Error submitting form", error);
}
};
return {
...toRefs(form),
onHandleSubmit,
};
},
};
</script>Attaching files
File uploads must be enabled in Settings โ General first (off by default on new forms). Use a FormData instance to send files alongside text fields. Don't set a Content-Type header manually, the browser fills it in (with the multipart boundary) for you.
Each file must be 1 MB or smaller, and a single submission may include at most 5 files. The server returns HTTP 413 if either limit is exceeded. See File Uploads โ for full details.
Simple example: single file
<template>
<form @submit.prevent="onHandleSubmit">
<input v-model="form.name" name="name" placeholder="Name" required />
<input
v-model="form.email"
type="email"
name="email"
placeholder="Email"
required
/>
<textarea
v-model="form.message"
name="message"
placeholder="Message"
required
></textarea>
<input
type="file"
name="resume"
accept="application/pdf"
@change="onPickFile"
/>
<button type="submit">Send</button>
</form>
</template>
<script>
import { reactive, ref, toRefs } from "vue";
export default {
setup() {
const form = reactive({ name: "", email: "", message: "" });
const resume = ref(null);
const onPickFile = (event) => {
resume.value = event.target.files?.[0] ?? null;
};
const onHandleSubmit = async () => {
const formData = new FormData();
formData.append("name", form.name);
formData.append("email", form.email);
formData.append("message", form.message);
if (resume.value) formData.append("resume", resume.value);
const res = await fetch(
"https://forms-api.basestack.co/v1/s/[KEY]?mode=rest",
{
method: "POST",
headers: { Accept: "application/json" },
body: formData,
},
);
const data = await res.json();
if (data.code === 200) console.log("Submitted");
};
return { ...toRefs(form), resume, onPickFile, onHandleSubmit };
},
};
</script>Complex example: multiple files with validation
The pattern below holds picked files in a ref, validates size and count before submission, and lets the user remove individual files from the list.
<template>
<form @submit.prevent="onHandleSubmit">
<input v-model="form.full_name" name="full_name" placeholder="Full name" required />
<input v-model="form.email" type="email" name="email" placeholder="Email" required />
<button type="button" :disabled="files.length >= MAX_FILES" @click="$refs.picker.click()">
Attach files ({{ files.length }} / {{ MAX_FILES }})
</button>
<input
ref="picker"
type="file"
multiple
hidden
@change="onPickFiles"
/>
<ul>
<li v-for="(file, index) in files" :key="`${file.name}-${index}`">
{{ file.name }} ยท {{ (file.size / 1024).toFixed(1) }} KB
<button type="button" @click="removeFile(index)">Remove</button>
</li>
</ul>
<button type="submit">Submit application</button>
</form>
</template>
<script>
import { reactive, ref, toRefs } from "vue";
const MAX_FILE_SIZE = 1 * 1024 * 1024;
const MAX_FILES = 5;
export default {
setup() {
const form = reactive({ full_name: "", email: "" });
const files = ref([]);
const onPickFiles = (event) => {
const picked = Array.from(event.target.files ?? []);
event.target.value = "";
const remaining = Math.max(0, MAX_FILES - files.value.length);
const accepted = [];
for (const file of picked) {
if (file.size > MAX_FILE_SIZE) {
alert(`"${file.name}" exceeds the 1 MB limit.`);
continue;
}
if (accepted.length >= remaining) {
alert(`Up to ${MAX_FILES} files allowed.`);
break;
}
accepted.push(file);
}
files.value = [...files.value, ...accepted];
};
const removeFile = (index) => {
files.value = files.value.filter((_, i) => i !== index);
};
const onHandleSubmit = async () => {
const formData = new FormData();
formData.append("full_name", form.full_name);
formData.append("email", form.email);
for (const file of files.value) {
formData.append("portfolio", file);
}
const res = await fetch(
"https://forms-api.basestack.co/v1/s/[KEY]?mode=rest",
{
method: "POST",
headers: { Accept: "application/json" },
body: formData,
},
);
const data = await res.json();
if (data.code === 200) {
files.value = [];
} else {
alert(data.message ?? "Submission failed.");
}
};
return {
...toRefs(form),
files,
MAX_FILES,
onPickFiles,
removeFile,
onHandleSubmit,
};
},
};
</script>