1
votes

I'm fairly new to Vue and don't fully understand the error I put as the title. I've read other posts about this error and haven't been able to figure out how to fix this issue for my project. I'm trying to make a file uploader that is written in Vue and interacts with Laravel on the backend. I understand that this property is undefined, however it seems fine before I attempt to upload a file. The files actually upload just fine in the backend, but after it uploads I get this error in the console when it's trying to display:

[Vue warn]: Error in render: "TypeError: file is undefined"
found in ---> at resources/js/components/ActionLogComponent.vue

Here's the relevant code:

<div class="form-group filezone">
    <input type="file" id="files" ref="files" multiple v-on:change="handleFiles()" />
    <p>Drop files here <br>or click to search.</p>                  

    <div v-for="(file, key) in files" class="file-listing">
        <img class="preview" v-bind:ref="'preview' + parseInt(key)" /> {{ file.name }}
        <div class="success-container" v-if="file.id > 0">
            Success
            <input type="hidden" :name="input_name" :value="file.id" />
        </div>
        <div class="remove-container" v-else>
            <a class="remove" v-on:click="removeFile(key)">Remove</a>
        </div>
    </div>

    <a class="submit-button" v-on:click="submitFiles()" v-show="files.length > 0">Submit</a>
</div>

And here is the relevant part of the export from the vue file

export default {
        props: ['companyName', 'userFullName', 'input_name', 'post_url'],
        data() {
            return {
                actions: [],
                files: [],
                viewing: '',
                csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
                createAction: {
                    errors: [],
                    date: '',
                    company: '',
                    name: '',
                    communication_type: '',
                    contact: '',
                    current_status: '',
                    action_item: ''
                },
                archiveAction: {
                  id: ''
                },
                url: ''
            }
        },

I have this method in my methods part that handles the file upload.

submitFiles() {
              for(let i = 0; i < this.files.length; i++) {
                if(this.files[i].id) {
                  continue;
                }

                //create form data to send
                let formData = new FormData();

                formData.append('file', this.files[i]);
                formData.append('viewing', this.viewing);

                axios.post('/upload-product-file', 
                  formData,
                  {
                    headers: {
                      'Content-Type': 'multipart/form-data'
                    }
                  })
                  .then(function(data) {
                    this.files[i].id = data['data'].id;
                    this.files.splice(i, 1, this.files['id']);
                    console.log('success');
                  }.bind(this))
                  .catch(function(error) {
                    console.log(error);
                  });

                  console.log('Just uploaded image. Files array should come next.');
                  console.log(this.files);
              }
            }

UPDATE Code for handleFiles():

handleFiles() {
              let uploadedFiles = this.$refs.files.files;

              for(var i = 0; i < uploadedFiles.length; i++) {
                this.files.push(uploadedFiles[i]);
              }

              this.getImagePreviews();
            },

Thank you in advance for any help or insight on this!

2
Please, add relevant code for handleFiles as well. - aBiscuit
Hi, no problem, just updated with the code. Thank you! - Frank A.

2 Answers

0
votes

Try adding file to your data export

data() {
return {
   actions: [],
   file: '',
   files: [],
   viewing: '',

I think is because you trying to access the file while files are null so technically you never actually loop through the files so you are not creating the file object. The other thing is you can use in the div I would check to if files !== null that way it avoids giving you any errors. meaning if the files are null it does't try to render the rest of what's inside the div, avoiding the errors.

Here is a good read on this https://medium.com/devmarketer/how-to-add-conditional-statements-to-v-for-loops-in-vue-js-c0b4d17e7dfd

I hope this helps

0
votes

I spent most of the day banging my head against the wall with this problem and since I was following a tutorial to help me build this I decided to go through the code again, line by line. It turns out in the submitFiles method there's this line:

this.files.splice(i, 1, this.files['id']);

which actually removes one element from the files array. I'm not certain if the author of the tutorial had a specific intention for this line of code or not, but they didn't explain what it was for. What I realized was happening though is it removes one element of the array each iteration of the for loop, which at some point empties the entire array. When I commented this line out, I no longer get the error. I don't know that this is actually the correct answer to my problem, but for now I'll just run with it since Vue no longer complains.