File upload in vuetify

Viewed 105090

I'm using Vuetify.js components for my front-end in Vue.js and want to create a user registration form with file upload. I'm able to create the form using v-text-field (a Vuetify component).

  • How can I upload the file that is selected (input)?
  • Which component should I use or is there any other alternative way?
4 Answers

Vue JS do not have file-input feature till today, so you can tweak v-text-field to work like image input field. The concept is, create an file input field and then hide it using css, and add an event in v-text-field to trigger that specific file input field to upload image. I have attached snippet please do play with that, and I also do have a fiddle created using vue and vuetify, visit here. Thanks!

new Vue({
  el: '#app',
  data: () => ({
    title: "Image Upload",
    dialog: false,
    imageName: '',
    imageUrl: '',
    imageFile: ''
  }),

  methods: {
    pickFile() {
      this.$refs.image.click()
    },

    onFilePicked(e) {
      const files = e.target.files
      if (files[0] !== undefined) {
        this.imageName = files[0].name
        if (this.imageName.lastIndexOf('.') <= 0) {
          return
        }
        const fr = new FileReader()
        fr.readAsDataURL(files[0])
        fr.addEventListener('load', () => {
          this.imageUrl = fr.result
          this.imageFile = files[0] // this is an image file that can be sent to server...
        })
      } else {
        this.imageName = ''
        this.imageFile = ''
        this.imageUrl = ''
      }
    }
  }
})
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">
<link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
  <v-app>
    <v-toolbar dark color="primary">
      <v-toolbar-side-icon></v-toolbar-side-icon>
      <v-toolbar-title class="white--text">{{ title }}</v-toolbar-title>
      <v-spacer></v-spacer>
      <v-btn icon @click="dialog = !dialog">
        <v-icon>link</v-icon>
      </v-btn>
    </v-toolbar>
    <v-content>
      <v-container fluid>
        <v-flex xs12 class="text-xs-center text-sm-center text-md-center text-lg-center">
          <img :src="imageUrl" height="150" v-if="imageUrl"/>
          <v-text-field label="Select Image" @click='pickFile' v-model='imageName' prepend-icon='attach_file'></v-text-field>
          <input
            type="file"
            style="display: none"
            ref="image"
            accept="image/*"
            @change="onFilePicked"
          >
        </v-flex>
        <v-dialog v-model="dialog" max-width="290">
          <v-card>
            <v-card-title class="headline">Hello World!</v-card-title>
            <v-card-text>
              Image Upload Script in VUE JS
              <hr>
              Yubaraj Shrestha
              <br>http://yubarajshrestha.com.np/
            </v-card-text>
            <v-card-actions>
              <v-spacer></v-spacer>
              <v-btn color="green darken-1" flat="flat" @click.native="dialog = false">Close</v-btn>
            </v-card-actions>
          </v-card>
        </v-dialog>
      </v-container>
    </v-content>
  </v-app>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify/dist/vuetify.js"></script>

Latest version (V2.0.5) while editing this post dated Aug 11, 2019, there's a dedicated file input option. Please follow the link below for official documentation: https://vuetifyjs.com/en/components/file-inputs.

An easy trick is:

<v-btn color="success" @click="$refs.inputUpload.click()">Success</v-btn>
<input v-show="false" ref="inputUpload" type="file" @change="yourFunction" >

Just create an input with the following properties:

  • type=file
  • ref=inputUpload this works like an id, you could name it like you want
  • v-show=false this hides input

Then make a button that when you click it, it fires a click event on the input Upload Button.

Good news.

Starting with version 2.0.0.-beta.8 v-file-input is available in Vuetify. You're supposed to use it like:

<template>
  <v-file-input accept=".txt" label="Select File..."></v-file-input>
</template>

EDIT (SNIPPET ADDITION):

A basic usage for handling an image file can be implemented as follows.

Thanks to @Begueradj pointing there is even no need for handling @change event for tracking the file change and making the example even more precise:

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data: () => ({
    file: null,
    imageUrl: null
  }),
  methods: {
    onUpload() {
      console.log(this.file)
    }
  }
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@3.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">

<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>

<div id="app">
  <v-app>
    <v-content>
      <v-container>
        <v-file-input 
          v-model="file" 
          label="Select Image File..." 
          accept="image/*"
        ></v-file-input>
        <v-btn color="primary" @click="onUpload">Upload</v-btn>
      </v-container>
    </v-content>
  </v-app>
</div>

Related