I have a base component that should have the ability to upload multiple files to firestore. Since I want to be able to use this component across multiple points in my app, I want to take advantage of slots so I can change the element that is covering the hidden input tag. So whether it be a button, an svg, etc. I still want the input to trigger the click event.
Currently, only the default img
tag works to trigger the @change
event.
Do I need to pass more props? How can I make this work in my current state?
If you need anymore information please let me know!
Cheers!
Note: I've yet to get the multiple file selection for firestore upload working, but am working on it.
UploadMediaFiles.vue (child)
<template>
<div class="upload-media-files">
<input
id="input-file"
type="file"
accept="image/*"
@change="addMedia"
class="_add-media-input"
/>
<label for="input-file">
<slot>
<img
src="https://www.clipartmax.com/png/middle/142-1422132_png-file-svg-upload-file-icon-png.png"
alt=""
/>
</slot>
</label>
</div>
</template>
<script>
export default {
name: 'UploadMediaFiles',
props: {
multiple: { type: Boolean },
accept: { type: String },
},
data() {
return {
files: [],
}
},
computed: {},
methods: {
async addMedia(event) {
const selectedFiles = event.target.files
console.log(`selectedFiles → `, selectedFiles)
this.files.push(selectedFiles)
this.$emit('selected', this.files)
},
},
}
</script>
SelectAndPreviewFiles (parent)
<template>
<div class="select-and-preview-files">
<UploadMediaFiles accept="image/*" :multiple="true" @selected="(files) => doSomething(files)">
<button>upload file</button>
</UploadMediaFiles>
</div>
</template>
<script>
import UploadMediaFiles from '../atoms/UploadMediaFiles.vue'
export default {
name: 'SelectAndPreviewFiles',
components: {
UploadMediaFiles,
},
props: {},
data() {
return {}
},
computed: {},
methods: {
doSomething(files) {
console.log(`files → `, files)
},
},
}
</script>
You could pass a method to the slot that invokes the hidden input's click
-handler:
In UploadMediaFiles
, add a template ref to the input:
<input ref="myInput">
In UploadMediaFiles
, create a component method that invokes the input's click
-handler:
export default {
methods: {
openFileDialog() {
this.$refs.myInput.click()
}
}
}
In UploadMediaFiles
, pass the component method to the slot:
<slot :openFileDialog="openFileDialog">
In SelectAndPreviewFiles
, bind the slot prop as your button's click
-handler:
<UploadMediaFiles v-slot="{ openFileDialog }">
<button @click="openFileDialog">Upload files</button>
</UploadMediaFiles>