Vue
Learn how to configure Vue for use with Filebase.
What is Vue?
Vue is an open-source JavaScript framework used for building user interfaces and single-page applications (SPAs). Vue is designed to be incrementally adoptable, which means that it can be integrated into an existing project or used to build a new project from scratch. It is also highly modular, with a core library that focuses on the view layer of an application and a set of optional libraries that can be used to add more functionality.
Read below to learn how to use Vue with Filebase.
1. Start by creating a new directory for your Vue app, then navigate into that directory and initialize the workspace:
mkdir filebase-vue-app
cd filebase-vue-app
npm init
Accept the default options when prompted.
2. Next, install the following packages:
npm install --save express multer dotenv cors body-parser mongodb multer-s3 aws-sdk
3. Create an .env
file with the following environment variables:
.env
file with the following environment variables:DATABASE=mongodb://127.0.0.1:27017/
PORT=5005
AWSAccessKeyId=FILEBASE_ACCESS_KEY
AWSSecretKey=FILEBASE_SECRET_KEY
AWSRegion=us-east-1
AWSBucket=filebase-bucket-name
Replace the environment variable values with the values that match your Filebase account and MongoDB configuration.
4. Create a new file called index.js
that contains the following code:
index.js
that contains the following code:const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const dotenv = require('dotenv')
const aws = require('aws-sdk')
const multer = require('multer')
const multerS3 = require('multer-s3')
const mongodb = require('mongodb')
dotenv.config()
const app = express()
//middleWare
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.use(cors())
aws.config.update({
apiVersion: "2006-03-01",
accessKeyId: process.env.AWSAccessKeyId,
secretAccessKey: process.env.AWSSecretKey,
region: process.env.AWSRegion
endpoint: "https://s3.filebase.com",
})
const s3 = new aws.S3()
const upload = multer({
storage: multerS3({
s3: s3,
bucket: process.env.AWSBucket,
acl: "public-read",
contentType: multerS3.AUTO_CONTENT_TYPE,
metadata: (req, file, cb) => {
cb(null, { fieldName: file.fieldname})
},
key: (req, file, cb) => {
cb(null, Date.now().toString() + file.originalname)
}
})
})
app.get('/', async (req, res) => {
res.status(200).send('S3 Upload Backend')
})
app.post('/', upload.single('photo'), async (req, res) => {
try {
const users = await loadUsersCollection();
await users.insertOne({
first_name: req.body.first_name,
last_name: req.body.last_name,
phone: req.body.phone,
email: req.body.email,
gender: req.body.gender,
photo: req.file.location,
})
res.status(201).send('success')
}
catch (err) {
res.status(500).send({
error: 'error occured creating user'
})
}
})
async function loadUsersCollection () {
const client = await mongodb.MongoClient.connect(process.env.DATABASE, {
useNewUrlParser: true,
useUnifiedTopology: true
})
return client.db('vue-multers3').collection('users')
}
const port = process.env.PORT || 5000
app.listen(port, () => {
console.log(server started on port ${port})
});
5. Then, start the server with the command:
node index.js
6. Next, install the Vue package to get started on the front end of the Vue app:
npm install -g @vue/cli
7. Then, create a new Vue app with the command:
vue create filebase-vue-app
8. Navigate inside the new Vue app directory and add the Vuetify package:
cd vue-multers3-frontend
vue add vuetify
9. Then, start the Vue front end with the command:
npm run serve
10. Navigate to the localhost:8080
address to view the Vue app:
localhost:8080
address to view the Vue app:11. Next, create a new file called register.vue
in the components folder. Insert the following code into this file:
register.vue
in the components folder. Insert the following code into this file:<template>
<v-container fluid class="my-3">
<v-row align="center" justify="center">
<v-col cols="12">
<v-card style="width: 100%" flat>
<div class="text-center pt-6"><h1 class="font-weight-light display-2 primary--text">Register!</h1></div>
<v-row class="pa-4">
<v-col cols="12" md="6">
<v-img src="@/assets/contactus.jpg" class="d-block ml-auto mr-auto" max-width="350px" />
</v-col>
<v-col cols="12" md="6">
<v-form ref="forma" v-model="form1" lazy-validation>
<v-row>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="first_name"
label="First Name"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="last_name"
label="Last Name"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="phone"
label="Phone"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="email"
label="Email"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="age"
type="number"
label="Age"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-file-input
v-model="photo"
:rules="photoRules"
accept="image/png, image/jpeg"
label="Pick a Picture"
outlined
dense
prepend-icon=""
prepend-inner-icon="mdi-camera"
hide-details
>
</v-file-input>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="password"
:append-icon="show1 ? 'mdi-eye' : 'mdi-eye-off'"
:rules="passwordRules"
:type="show1 ? 'text' : 'password'"
hint="At least 6 characters"
@click:append="show1 = !show1"
outlined
dense
hide-details
>
</v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="confirmPassword"
:append-icon="show1 ? 'mdi-eye' : 'mdi-eye-off'"
:rules="passwordConfirmation"
:type="show1 ? 'text' : 'password'"
hint="At least 6 characters"
@click:append="show1 = !show1"
outlined
dense
hide-details
>
</v-text-field>
</v-col>
<v-col
cols="12"
md="12"
>
<v-text-field
v-model="address"
label="Address"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
>
<v-btn
color="primary"
rounded
block
class="mt-3"
@click="onSubmit"
:disabled="!form1"
>
Submit
</v-btn>
</v-col>
</v-row>
</v-form>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-snackbar
v-model="snackbar"
:timeout="timeout"
color="success"
top
>
{{ message }}
</v-snackbar>
</v-container>
</template>
<script>
export default {
data () {
return {
message: 'success',
snackbar: false,
timeout: 2000,
show1: false,
form1: false,
submitSuccess: false,
first_name: '',
last_name: '',
phone: '',
email: '',
age: '',
photo: null,
address: '',
password: '',
confirmPassword: '',
photoRules: [v => !v || v.size < 5000000 || 'Image should be less than 5MB'],
passwordRules: [v => !!v || 'Password is required',
v => (v && v.length >= 6) || 'password should be 6 characters'],
passwordConfirmation: [v => !!v || 'Password is required',
v => (v === this.password) || 'password should match'],
required: [value => !!value || 'Required.']
}
}
}
</script>
<style>
</style>
12. Then, insert the following code in the app.vue
file:
app.vue
file:<template>
<v-app>
<v-app-bar
app
color="primary"
dark
>
<div class="d-flex align-center">
<v-img
alt="Vuetify Logo"
class="shrink mr-2"
contain
src="<https://cdn.vuetifyjs.com/images/logos/vuetify-logo-dark.png>"
transition="scale-transition"
width="40"
/>
<v-img
alt="Vuetify Name"
class="shrink mt-1 hidden-sm-and-down"
contain
min-width="100"
src="<https://cdn.vuetifyjs.com/images/logos/vuetify-name-dark.png>"
width="100"
/>
</div>
<v-spacer></v-spacer>
<v-btn
href="<https://github.com/vuetifyjs/vuetify/releases/latest>"
target="_blank"
text
>
<span class="mr-2">Latest Release</span>
<v-icon>mdi-open-in-new</v-icon>
</v-btn>
</v-app-bar>
<v-main>
<Register/>
</v-main>
</v-app>
</template>
<script>
import Register from './components/Register'
export default {
name: 'App',
components: {
Register
},
data: () => ({
//
})
}
</script>
13. If you refresh your Vue app, it should now resemble this:
14. Next, install the axois package:
npm install axios
15. Then, create the file registeraxios.vue
in the components folder and insert the following code:
registeraxios.vue
in the components folder and insert the following code:<template>
<v-container fluid class="my-3">
<v-row align="center" justify="center">
<v-col cols="12">
<v-card style="width: 100%" flat>
<div class="text-center pt-6"><h1 class="font-weight-light display-2 primary--text">Register!</h1></div>
<v-row class="pa-4">
<v-col cols="12" md="6">
<v-img src="@/assets/contactus.jpg" class="d-block ml-auto mr-auto" max-width="350px" />
</v-col>
<v-col cols="12" md="6">
<v-form ref="forma" v-model="form1" lazy-validation>
<v-row>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="first_name"
label="First Name"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="last_name"
label="Last Name"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="phone"
label="Phone"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="email"
label="Email"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="age"
type="number"
label="Age"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-file-input
v-model="photo"
:rules="photoRules"
accept="image/png, image/jpeg"
label="Pick a Picture"
outlined
dense
prepend-icon=""
prepend-inner-icon="mdi-camera"
hide-details
>
</v-file-input>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="password"
:append-icon="show1 ? 'mdi-eye' : 'mdi-eye-off'"
:rules="passwordRules"
:type="show1 ? 'text' : 'password'"
hint="At least 6 characters"
@click:append="show1 = !show1"
outlined
dense
hide-details
>
</v-text-field>
</v-col>
<v-col
cols="12"
md="6"
>
<v-text-field
v-model="confirmPassword"
:append-icon="show1 ? 'mdi-eye' : 'mdi-eye-off'"
:rules="passwordConfirmation"
:type="show1 ? 'text' : 'password'"
hint="At least 6 characters"
@click:append="show1 = !show1"
outlined
dense
hide-details
>
</v-text-field>
</v-col>
<v-col
cols="12"
md="12"
>
<v-text-field
v-model="address"
label="Address"
outlined
dense
hide-details
></v-text-field>
</v-col>
<v-col
cols="12"
>
<v-btn
color="primary"
rounded
block
class="mt-3"
@click="onSubmit"
:disabled="!form1"
>
Submit
</v-btn>
</v-col>
</v-row>
</v-form>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
<v-snackbar
v-model="snackbar"
:timeout="timeout"
color="success"
top
>
{{ message }}
</v-snackbar>
</v-container>
</template>
<script>
import axios from 'axios'
const url = '<http://localhost:5005/>'
export default {
data () {
return {
message: 'submission success',
snackbar: false,
timeout: 4000,
show1: false,
form1: false,
submitSuccess: false,
first_name: '',
last_name: '',
phone: '',
email: '',
age: '',
photo: null,
address: '',
password: '',
confirmPassword: '',
photoRules: [v => !v || v.size < 5000000 || 'Image should be less than 5MB'],
passwordRules: [v => !!v || 'Password is required',
v => (v && v.length >= 6) || 'password should be 6 characters'],
passwordConfirmation: [v => !!v || 'Password is required',
v => (v === this.password) || 'password should match'],
required: [value => !!value || 'Required.']
}
},
computed: {
photoValidation () {
if (this.photo) {
return true
} else return false
}
},
methods: {
clearForm () {
this.$refs.forma.reset()
},
async onSubmit () {
if (this.$refs.forma.validate() && this.photoValidation) {
const blob = this.photo
const formData = new FormData()
formData.append('first_name', this.first_name)
formData.append('last_name', this.last_name)
formData.append('photo', blob)
formData.append('phone', this.phone)
formData.append('email', this.email)
formData.append('age', this.age)
formData.append('password', this.password)
formData.append('address', this.address)
axios.post(url, formData).then((res) => {
if (res.status === 201) {
console.log(res)
this.clearForm()
this.snackbar = true
}
}).catch((err) => {
console.log(err.response)
})
}
}
}
}
</script>
<style>
</style>
16. Now, when a user submits the form in the Vue app, the image file they include in the form will be uploaded to the configured Filebase bucket!
Last updated