# File Inputs
# Default
<input type="file">
# Custom Style
<template>
<label class="flex items-center">
<div class="px-8 py-2 mr-2 text-sm font-medium bg-gray-300 rounded-sm cursor-pointer focus:bg-gray-500 focus:outline-none">
Select File
</div>
<p class="truncate">{{ value ? value.name : 'No file chosen' }}</p>
<input
class="hidden"
type="file"
@change="onChange"
>
</label>
</template>
<script>
export default {
data() {
return {
value: null,
}
},
methods: {
onChange(e) {
this.value = e.target.files[0];
},
},
};
</script>
# Custom Style With Image Preview
<template>
<label class="flex flex-col items-center">
<div class="flex items-center justify-center w-20 h-20 mb-2 text-xl text-gray-500 border border-dashed rounded select-none">
<img :src="imagePreviewPath" v-if="imagePreviewPath" class="object-cover w-full h-full">
<template v-else>+</template>
</div>
<div class="px-8 py-2 text-sm font-medium bg-gray-300 rounded-sm cursor-pointer focus:bg-gray-500 focus:outline-none">
Select File
</div>
<input
class="hidden"
type="file"
accept=".png, .jpg, .jpeg, .gif"
@change="onChange"
>
</label>
</template>
<script>
export default {
data() {
return {
value: null,
}
},
computed: {
imagePreviewPath() {
return this.value ? window.URL.createObjectURL(this.value) : null;
}
},
methods: {
onChange(e) {
this.value = e.target.files[0];
},
},
};
</script>
# Custom Style With Multiple Images
<template>
<label class="flex flex-col items-center">
<div class="px-8 py-2 mb-2 text-sm font-medium bg-gray-300 rounded-sm cursor-pointer focus:bg-gray-500 focus:outline-none">
Select Images
</div>
<div class="flex flex-wrap justify-center">
<div class="flex w-20 h-20 m-1 border border-dashed rounded select-none" v-for="file in files">
<img :src="file | objectURL" class="object-cover w-full h-full">
</div>
</div>
<input
class="hidden"
type="file"
accept=".png, .jpg, .jpeg, .gif"
@change="onChange"
multiple
>
</label>
</template>
<script>
export default {
data() {
return {
files: null,
}
},
methods: {
onChange(e) {
this.files = e.target.files;
},
},
filters: {
objectURL(file) {
return window.URL.createObjectURL(file);
}
}
};
</script>
# Custom Style for Direct Upload, with preview
Adaptation of Shrine's guide for Direct Upload, using Uppy
<template>
<div class="flex flex-col items-center">
<label ref="container" class="flex flex-col items-center">
<div class="flex items-center justify-center w-20 h-20 mb-2 text-xl text-gray-500 border border-dashed rounded select-none">
<img :src="previewSrc" v-if="previewSrc" class="object-cover w-full h-full">
<template v-else>+</template>
</div>
<input
type="hidden"
:name="inputName"
:value="fileData"
>
</label>
</div>
</template>
<script>
import 'uppy/dist/uppy.min.css';
import '@uppy/file-input/dist/style.css'
import {
Core as createUppyUploader,
FileInput,
ThumbnailGenerator,
XHRUpload,
} from 'uppy';
export default {
props: {
inputName: { type: String, default: '' },
},
data() {
return {
fileData: null,
previewSrc: null,
};
},
mounted() {
const container = this.$refs.container;
const uppy = createUppyUploader({
autoProceed: true,
})
.use(FileInput, { target: container, locale: { strings: { chooseFiles: "Select File" } } })
.use(ThumbnailGenerator, { thumbnailHeight: 600 })
.use(XHRUpload, { endpoint: '/upload' });
uppy.on('upload-success', (file, response) => {
const uploadedFileData = response.body.data;
this.fileData = JSON.stringify(uploadedFileData);
});
uppy.on('thumbnail:generated', (file, preview) => {
this.previewSrc = preview;
});
},
};
</script>
.uppy-FileInput-btn {
@apply px-8 py-2 text-sm font-medium bg-gray-300 rounded-sm cursor-pointer text-gray-700 border-0;
}
.uppy-FileInput-btn:focus {
@apply bg-gray-500 outline-none;
}
.uppy-FileInput-btn:hover {
@apply bg-gray-300 text-gray-700;
}
← Buttons Form Inputs →