Nikki's avatar
Level 1

Getting a image preview to be removed from list

I'm trying to have a page that when you upload images it shows a preview of it and if you want you can remove it from the list. I have the preview working and all that but I can't get the remove button to work. I'm using Vue and laravel

I also get this error

 Error in render: "TypeError: _vm.files[index] is undefined"
<template>
    <!-- isDragging = if(isDragging) -->
    <div class="uploader" 
            @dragenter="OnDragEnter" 
            @dragleave="OnDragLeave" 
            @dragover.prevent 
            @drop="onDrop" 
            :class="{ dragging: isDragging }">
        
        <div class="upload-control" v-show="images.length">
            <label for="file">Select a file</label>
            <button @click="upload">Upload</button>
        </div>

        <!-- only shows if there is no images -->
        <div v-show="!images.length">
            <i class="fa fa-cloud-upload"></i>
            <p>Drag your images here</p>
            <div>OR</div>
            <div class="file-input">
                <label for="file">Select a file</label>
                <input type="file" id="file" @change="onInputChange" multiple>
            </div>
        </div>

        <!-- if there is images -->
        <div class="images-preview" v-show="images.length">
            <div class="img-wrapper" v-for="(image, index) in images" :key="index">
                <img :src="image" :alt="`Image Uplaoder ${index}`">
                <div class="details">
                    <span class="name" v-text="files[index].name"></span>
                    <span class="size" v-text="getFileSize(files[index].size)"></span>
                </div>
                <div class="btn btn-danger" @click="funDeleteFile(index)">
                    Remove
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    data: () => ({
        isDragging: false,
        //Sets the dragCount to 0
        dragCount: 0,
        //Makes files an array, so that we can send the files to the server
        files: [],
        //Makes images an array, so that we can let the user see the images
        images: [],
         fileFilter: [],
    }),
    methods: {
        OnDragEnter(e) {
            //Prevents the default action of the browser
            e.preventDefault();
            
            // This lets the dragCount become 1, so that the image uploader changes colour
            this.dragCount++;

            // Changes the isDragging variable to true instead of false
            this.isDragging = true;

            return false;
        },
        OnDragLeave(e) {
            //Prevents the default action of the browser
            e.preventDefault();

            // This lets the dragcount become 0, so that the image uploader changes to it's original colour
            this.dragCount--;

            // This is if the dragCount is <= 0 then the isDragging variable is false
            if (this.dragCount <= 0)
                this.isDragging = false;
        },
        onInputChange(e) {
            // Grabs the files from the event
            const files = e.target.files;

            // Creates an array for files, so that we can loop thru it
            // Send the file to the addImage method via "this.addImage(file)"
            Array.from(files).forEach(file => this.addImage(file));
        },
        onDrop(e) {
            //Prevents the default action of the browser
            e.preventDefault();
            //Stops the propagation into the other elements inside the one we drop and file into
            e.stopPropagation();

            // This is to disable the dragging of the images
            this.isDragging = false;

            // Grabs the files from the event
            const files = e.dataTransfer.files;

            // Creates an array for files, so that we can loop thru it
            // Send the file to the addImage method via "this.addImage(file)"
            Array.from(files).forEach(file => this.addImage(file));
        },
        addImage(file) {
            //Checks if the file type is an image
            if (!file.type.match('image.*')) {
                this.$toastr.e(`${file.name} is not an image`);
                return;
            }

            this.files.push(file);

            const img = new Image(),
                reader = new FileReader();

            reader.onload = (e) => this.images.push(e.target.result);

            reader.readAsDataURL(file);
        },

        funDeleteFile(file){
            console.log('delete '+file)
            this.files.splice(file,1)
   
        },

        getFileSize(size) {
            const fSExt = ['Bytes', 'KB', 'MB', 'GB'];
            let i = 0;
            
            while(size > 900) {
                size /= 1024;
                i++;
            }

            return `${(Math.round(size * 100) / 100)} ${fSExt[i]}`;
        },
        upload() {
            const formData = new FormData();
            
            this.files.forEach(file => {
                formData.append('images[]', file, file.name);
            });

            axios.post('/images-upload', formData)
                .then(response => {
                    this.$toastr.s('All images uplaoded successfully');
                    // this.images = [];
                    // this.files = [];
                })
        }
    }
}
</script>
0 likes
5 replies
signar's avatar

@nikki It seems like you're using this.files.splice() correctly. Is your console.log() showing anything? And do you have Vue developers tool installed? If so, have you checked that the image has been removed from the files array?

Nikki's avatar
Level 1

@signar - When I click remove, on my Vue developer tool a file gets removed from the files array and nothing gets removed from the images array and in my console I get this error

[Vue warn]: Error in render: "TypeError: _vm.files[index] is undefined"
111
Nikki's avatar
Level 1

@signar - I did that as soon as I was done posting my previous answer. I can't believe it took me so long to get it working. Thank you so much for the help

Please or to participate in this conversation.