'Passing array to component, devtools sees it, the component does not

I'm passing an array to a component but the component sees the array as undefined. Here is the parent calling the component...

<FileList ref="files" class="ma-3 pa-0" :passFiles="true" :passedFiles="header.files"></FileList>

Vue devtools sees the array, it is valid. As seen in the screenshot below:

Yet in my created hook in the controller, it shows this.passedFiles as undefined. (this.passFiles, however, shows correctly as true.)

created(){
       console.log(this.passFiles,this.passedFiles); //this.passedFiles shows as undefined
       window.addEventListener("resize", this.onResize);
},

I dumped the array right before it gets sent to the component, and it is there, see screenshot:

I tried this just to make sure, and it gets passed to the array fine:

:passedFiles="[{0: '1'}]"

I'm pulling my hair out here. Here is the full component, it is long but it shows you everything

<template>
    <div>
        <div class="text-center pa-10" v-show="loading">
            <v-progress-circular
                :size="35"
                :width="3"
                color="primary"
                indeterminate
            ></v-progress-circular>
        </div>
        <v-data-table
            v-show="!loading"
            :headers="showActions ? headers : headersRead"
            :items="orderedFiles"
            :items-per-page="paginate"
            :footer-props="{'items-per-page-options':[paginate, 15, 30, 50, 100, -1]}"
            :hide-default-footer="oneFileOnly"
            class="elevation-1 custom-rounded-box ma-0 pa-0"
            ref="aWidth"
            :style="forceHeight&&$vuetify.breakpoint.mdAndUp ? 'height:'+forceHeight+'px;' : ''"
        >
            <template slot="no-data">
                <div>There are currently no files here</div>
            </template>
            <template v-slot:item.description="{item, index}">
                <v-row
                    no-gutters
                    style="flex-wrap: nowrap;"
                >
                    <v-col
                        cols="12"
                        md="11"
                        class="flex-grow-0 flex-shrink-0"
                    >
                        <v-tooltip bottom v-if="item.description">
                            <template v-slot:activator="{ on, attrs }">
                                <a
                                    v-if="item.gdoc"
                                    style="text-decoration: none; color: orange;"
                                    v-bind="attrs"
                                    v-on="on"
                                    @click.prevent="gdocDialog = true;editingFile = item"
                                    class="d-block text-truncate"
                                    :style="$vuetify.breakpoint.mdAndUp ? 'max-width:'+aWidth+'px;' : 'max-width:'+bWidth+'px;'"
                                >
                                    {{item.description}}
                                </a>
                                <a
                                    v-else
                                    :href="'/getFile?id='+item.id"
                                    style="text-decoration: none; color: orange;"
                                    v-bind="attrs"
                                    v-on="on"
                                    class="d-block text-truncate"
                                    :style="$vuetify.breakpoint.mdAndUp ? 'max-width:'+aWidth+'px;' : 'max-width:'+bWidth+'px;'"
                                >
                                    {{item.description}}
                                </a>
                            </template>
                            <span>{{item.file_name_original}}</span>
                        </v-tooltip>
                        <div v-else>
                            <a
                                v-if="item.gdoc"
                                style="text-decoration: none; color: orange;"
                                @click.prevent="gdocDialog = true;editingFile = item"
                                class="d-block text-truncate"
                                :style="$vuetify.breakpoint.mdAndUp ? 'max-width:'+aWidth+'px;' : 'max-width:'+bWidth+'px;'"
                            >
                                {{item.file_name_original}}
                            </a>
                            <a
                                v-else
                                :href="'/getFile?id='+item.id"
                                style="text-decoration: none; color: orange;"
                                class="d-block text-truncate"
                                :style="$vuetify.breakpoint.mdAndUp ? 'max-width:'+aWidth+'px;' : 'max-width:'+bWidth+'px;'"
                            >
                                {{item.file_name_original}}
                            </a>
                        </div>
                    </v-col>
                    <v-col
                        cols="12"
                        md="1"
                        style="min-width: 30px; max-width: 30px;"
                        class="flex-grow-1 flex-shrink-0"
                        v-show="$vuetify.breakpoint.mdAndUp"
                    >
                        <v-edit-dialog
                            :return-value.sync="item.description"
                            @save="editFileInline()"
                            @open="inlineEditOpen(item, index)"
                            v-if="showActions"
                        >
                            <template v-slot:input>
                                <v-text-field
                                    ref="inline_file"
                                    v-model="editingFile.description"
                                    label="Edit"
                                    single-line
                                    counter
                                ></v-text-field>
                            </template>
                            <v-tooltip bottom>
                                <template v-slot:activator="{ on, attrs }">
                                    <v-icon
                                        small
                                        class="ml-2"
                                        color="orange"
                                        v-bind="attrs"
                                        v-on="on"
                                        width="100%"
                                    >
                                        mdi-pencil
                                    </v-icon>
                                </template>
                                <span>Edit the file description</span>
                            </v-tooltip>
                        </v-edit-dialog>
                    </v-col>
                </v-row>

            </template>
            <template v-slot:item.icon="{ item }">
                <v-icon
                    :color="item.icon_color"
                >
                    {{item.icon}}
                </v-icon>
            </template>

            <template v-slot:item.uploaded="{ item }">
                <v-tooltip bottom>
                    <template v-slot:activator="{ on, attrs }">
                        <div v-bind="attrs"
                             v-on="on">
                            {{item.date_difference}}
                        </div>
                    </template>
                    <span>
                        <v-avatar
                            size="26px"
                            class="mr-2"
                        >
                            <img
                                :src="'/img/profile-pictures/'+item.user.profile_photo_thumb"
                            >
                        </v-avatar>
                        {{item.pretty_date}} by {{item.user.full_name}}</span>
                </v-tooltip>
            </template>

            <template v-slot:item.actions="{item}" v-if="showActions">
                <v-tooltip bottom>
                    <template v-slot:activator="{ on, attrs }">
                        <v-icon
                            small
                            color="red"
                            @click="showDeleteDialog(item)"
                            v-bind="attrs"
                            v-on="on"
                        >
                            mdi-delete
                        </v-icon>
                    </template>
                    <span>Delete</span>
                </v-tooltip>
            </template>
        </v-data-table>


        <!-- Upload modal -->
        <v-dialog
            v-model="fileUploadDialog"
            max-width="500px"
            width="500px"
            :transition="transitionSiteWide()"
            persistent
            v-if="showActions"
        >
            <v-card>
                <v-progress-linear
                    indeterminate
                    color="yellow darken-2"
                    v-show="fileUploadProcess"
                ></v-progress-linear>
                <v-toolbar
                    dark
                    class="primary"
                    dense
                    elevation="0"
                >
                    <v-icon class="mr-2">mdi-cloud-upload</v-icon>
                    <v-toolbar-title class="text">Upload File(s)</v-toolbar-title>
                    <v-spacer></v-spacer>
                </v-toolbar>

                <v-card-text class="pt-3" v-show="!fileUploadGDoc">
                    <template>
                        <v-file-input
                            small-chips
                            :label="!oneFileOnly ? 'Upload multiple files by clicking here' : 'Click here to upload a file'"
                            type="file"
                            ref="files"
                            :accept="acceptedFiles()"
                            @change="onFilePicked()"
                            :key="componentKey"
                            show-size
                            counter
                            :multiple="!oneFileOnly"
                            :rules="!oneFileOnly ? rules : rulesSingle"
                        ></v-file-input>
                    </template>
                </v-card-text>
                <v-card-text class="pt-3" v-show="fileUploadGDoc">
                    <v-text-field
                        ref="gdoc_description"
                        v-model="gdoc_description"
                        label="Description"
                        :rules="gdoc_description_rules"
                        prepend-icon="mdi-pencil"
                    ></v-text-field>
                    <v-text-field
                        ref="gdoc_link"
                        v-model="gdoc_link"
                        label="Link to your Google Document"
                        :rules="gdoc"
                        prepend-icon="mdi-google-drive"
                    ></v-text-field>
                </v-card-text>
                <v-card-actions>
                    <v-spacer></v-spacer>
                    <v-btn
                        text
                        @click="ok"
                    >
                        Close
                    </v-btn>
                    <v-btn
                        class="primary"
                        text
                        v-show="fileUploadButton"
                        @click="uploadFiles()"
                        :loading="fileUploadProcess"
                    >
                        Upload
                    </v-btn>
                    <v-btn
                        class="primary"
                        text
                        v-show="gdocValidated()"
                        @click="uploadFiles()"
                        :loading="fileUploadProcess"
                    >
                        Attach
                    </v-btn>
                </v-card-actions>
            </v-card>
        </v-dialog>

        <!-- Delete dialog -->
        <v-dialog
            v-if="showActions"
            v-model="deleteFileConfirm"
            max-width="400px"
            :transition="transitionSiteWide()"
        >
            <v-card elevation="0">
                <v-progress-linear
                    indeterminate
                    color="yellow darken-2"
                    v-show="deleteFileLoading"
                ></v-progress-linear>
                <v-toolbar
                    dark
                    class="primary"
                    dense
                    elevation="0"
                >
                    <v-icon class="mr-2">mdi-text-box-minus</v-icon>
                    <v-toolbar-title class="text">{{editingFile.description ? editingFile.description : editingFile.file_name_original}}</v-toolbar-title>
                    <v-spacer></v-spacer>
                </v-toolbar>
                <v-card-text class="pb-0">
                    <v-container>
                        <p>Are you sure you want to delete this file?</p>
                        <p>{{editingFile.description ? editingFile.description : editingFile.file_name_original}}
                            will be removed from the system.</p>
                    </v-container>
                </v-card-text>
                <v-card-actions>
                    <v-btn
                        text
                        @click="deleteFileConfirm = false"
                    >
                        Close
                    </v-btn>
                    <v-spacer></v-spacer>
                    <v-btn
                        class="primary"
                        text
                        @click="deleteSet()"
                    >
                        Yes, delete this file
                    </v-btn>
                </v-card-actions>
            </v-card>
        </v-dialog>

        <!-- Gdoc dialog -->
        <v-dialog
            v-model="gdocDialog"
            max-width="1000px"
            width="100%"
            :transition="transitionSiteWide()"
        >
            <v-card elevation="0">
                <v-toolbar
                    dark
                    color="teal"
                    dense
                    elevation="0"
                >
                    <v-icon class="mr-2">mdi-google-drive</v-icon>
                    <v-toolbar-title class="text">{{editingFile.description ? editingFile.description : editingFile.file_name_original}}</v-toolbar-title>
                    <v-spacer></v-spacer>
                </v-toolbar>
                <v-card-text class="pa-0">
                    <iframe ref="gdocIframe" :src="editingFile.file_name_original" :style="'height:'+iframeHeight+'px;width:100%;border:0'"></iframe>
                </v-card-text>
                <v-card-actions>
                    <v-spacer></v-spacer>
                    <v-btn
                        text
                        @click="gdocDialog = false"
                    >
                        Close
                    </v-btn>
                    <v-btn
                        class="primary"
                        text
                        link
                        @click="openGdoc(editingFile.file_name_original);"
                    >
                        Open in new window
                    </v-btn>
                </v-card-actions>
            </v-card>
        </v-dialog>

    </div>
</template>

<script>
    export default {
        props: {
            type: String,
            id: [Number, String],
            paginate: Number,
            fileUploadDialog: Boolean,
            fileUploadGDoc: Boolean,
            ok: Function,
            showActions: Boolean,
            forceHeight: { type: Number, default: 0 },
            oneFileOnly: Boolean,
            passFiles: Boolean,
            passedFiles: Array,
        },
        data () {
            return {
                headers: [
                    {
                        text: '',
                        align: 'start',
                        sortable: false,
                        value: 'icon',
                        width: '20px'
                    },
                    { text: 'Description', value: 'description', sortable: false, },
                    { text: 'Uploaded', value: 'uploaded', width: '150px' },
                    { text: 'Actions', value: 'actions', sortable: false, width: '80px', align: 'center' },
                ],
                headersRead: [
                    {
                        text: '',
                        align: 'start',
                        sortable: false,
                        value: 'icon',
                        width: '20px'
                    },
                    { text: 'Description', value: 'description', sortable: false, },
                    { text: 'Uploaded', value: 'uploaded', width: '150px' },
                ],
                rules: [
                    files => !files || !files.some(file => file.size > 20_097_152) || 'Each file cannot exceed 20mb',
                ],
                rulesSingle: [

                ],
                gdoc: [
                    (value) => !!value || "Required",
                    (value) => this.isURL(value) || "URL is not valid",
                ],
                gdoc_description_rules: [
                    (value) => !!value || "Required",
                ],
                files: [],
                fileUploadButton: false,
                deleteFileConfirmLoading: false,
                fileUpload: false,
                fileUploadProcess: false,
                componentKey: 0,
                postFormData: new FormData(),
                editingFile: {
                    description: null,
                    index: null,
                    file_name_original: null,
                },

                deleteFileConfirm : false,
                deleteFileLoading: false,
                gdoc_link: null,
                gdoc_description: null,
                gdocDialog: false,
                iframeHeight: 0,
                aWidth: 0,
                loading: true,
            }
        },
        computed:{
            orderedFiles: function () {
                return _.orderBy(this.files, 'created_at', 'desc')
            },
        },
        watch: {
            files: {
                immediate: false,
                handler(){
                    if(this.files){
                        this.total = this.files.length;
                        this.$emit('totalFiles', this.total);
                    }else{
                        this.total = 0;
                    }

                },
            },
            id: {
                immediate: false,
                handler(){
                    this.getFiles()
                },
            }
        },
        methods: {
            async getFiles(){
                this.loading = true;
                await axios
                    .get('/app/files/getFiles?id=' + this.id + '&type=' + this.type)
                    .then(response => {
                        if (response.data.length) {
                            this.files = response.data;
                            this.$emit('totalFiles', this.files.length);
                            this.resize();
                            this.loading = false;
                        } else {
                            this.files = [];
                            this.$emit('totalFiles', 0);
                            this.loading = false;
                        }
                    })
                    .catch(error => {
                        this.majorError();
                    })
                    .finally()
            },
            onFilePicked(e) {
                this.postFormData = new FormData();
                if(this.$refs.files.validate()){
                    this.fileUploadButton = true;
                }
                this.postFormData = new FormData();
                for(let key in event.target.files){
                    if(key >= 0){
                        this.postFormData.append( 'files[]', event.target.files[key]);
                    }
                }

            },
            async uploadFiles(){
                this.fileUploadProcess = true;
                this.postFormData.append('type', this.type);
                this.postFormData.append('id', this.id);
                this.postFormData.append('gdoc', this.fileUploadGDoc);
                this.postFormData.append('gdoc_link', this.gdoc_link);
                this.postFormData.append('gdoc_description', this.gdoc_description);
                const res = await this.callApi('post', '/app/files/uploadFiles', this.postFormData);
                if(res.status===200){
                    this.componentKey++; //reset trick
                    this.snackbar(res.data.msg,res.data.type);
                    this.ok();
                    this.fileUploadProcess = false;
                    this.gdoc_link = null;
                    this.gdoc_description = null;
                    this.$refs.gdoc_link.reset()
                    this.$refs.gdoc_description.reset()

                    if(res.data.files){
                        for (const file of res.data.files) {
                            this.files.push(file);
                        }
                    }
                    this.resize();
                    this.fileUploadButton = false;
                }else{
                    this.fileUploadProcess = false;
                    this.snackbar(res.data.msg, res.data.type);
                }

            },

            inlineEditOpen (item) {
                let obj = { ...item, editingIndex: this.files.indexOf(item) }
                this.editingFile = obj;
            },
            async editFileInline(){

                const file = Object.assign({}, this.editingFile); //Turn array into object for laravel
                const res = await this.callApi('post', '/app/files/updateFile',
                    {file: file});

                if(res.status===201){
                    this.files[this.editingFile.editingIndex].description = this.editingFile.description;
                    this.snackbar(this.editingFile.description + " has been edited successfully", 'success');
                    this.resize();
                }else{
                    if(res.status===422){
                        for(let i in res.data.errors) {
                            this.snackbar(res.data.errors[i][0], 'error');
                        }
                    }else{
                        this.snackbar("There has been an error, we don't have any more information for you", 'error');
                    }
                }
            },

            showDeleteDialog(file){
                this.deleteFileConfirm = true;
                let obj = { ...file, index: this.files.indexOf(file)}
                this.editingFile= obj;
            },
            async deleteSet(){
                this.deleteFileLoading = true;
                const res = await this.callApi('post', '/app/files/deleteFile', this.editingFile);

                if(res.status===200){
                    this.files.splice(this.editingFile.index, 1);
                    this.snackbar("File deleted successfully", 'success');
                    this.deleteFileConfirm = false;
                }else{
                    if(res.status===422){
                        this.snackbar(res.data.msg, 'error');
                    }
                }
                this.deleteFileLoading = false;
            },

            gdocValidated(){
                if(this.gdoc_link&&this.$refs.gdoc_link.validate()&&this.gdoc_description){
                    return true;
                }
            },
            openGdoc(url){
                window.open(url, '_blank').focus();
            },

            onResize() {
                this.iframeHeight =  window.innerHeight - 220;
                if(this.showActions){
                    this.aWidth = this.$refs.aWidth.$el.clientWidth - 355;
                    this.bWidth = this.$refs.aWidth.$el.clientWidth - 150;
                }else{
                    this.aWidth = this.$refs.aWidth.$el.clientWidth - 270;
                    this.bWidth = this.$refs.aWidth.$el.clientWidth - 65;
                }
            },
            resize(){
                setTimeout(() =>  window.dispatchEvent(new Event('resize')), 1);
            },
        },
        async mounted(){
            if(this.passFiles){
                this.files = this.passedFiles;
                //console.log(this.passedFiles,this.files)
                this.loading = false;
            }else{
                this.getFiles();
            }
            this.onResize();
            this.resize();
        },
        created(){
            console.log(this.passFiles,this.passedFiles); //this.passedFiles shows as undefined
            window.addEventListener("resize", this.onResize);
        },
        destroyed(){
            window.removeEventListener("resize", this.onResize);
            this.editingFile = null;
        },
    }
</script>

What am I missing here?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source