krismanning's avatar

Vue components stop working after upgrading Laravel project to Bootstrap 4

Hi,

First time posting for help on laracasts but this problem is driving me insane and I'm hoping somebody can tell me what I've missed.

I have a project in Laravel (originally 5.4, now upgraded to 5.6) All working fine.

It uses a couple of Vue components to handle multiple file uploads. No problem there.

Today I upgraded the project from BS3 to BS4 and started working through all the blade files to get them working with BS4. Now my Vue components just refuse to run, and Chrome Vue dev tools shows they are not registering. Vue loads and an app is created. Its just the components won't register or run. No errors in console and Vue tools just shows the root instance.

Anybody seen anything like this? I've compared my app.js from old version to new version and apart from the changes needed for BS4 everything looks fine, the Vue components are required as before. No errors when compiling.

It's driving me nuts.

Here's my app.js

require('./bootstrap');

window.Vue = require('vue');

window.Event = new class {
    constructor () {
        this.vue = new Vue();
    }

    fire(event, data = null) {
        this.vue.$emit(event, data);
    }

    listen(event, callback) {
        this.vue.$on(event, callback);
    }
 }

Vue.component('file-management', require('./components/FileManagement.vue'));
Vue.component('attachment-list', require('./components/AttachmentList.vue'));
Vue.component('half-circle-spinner', require('./components/Spinners.vue'));

const app = new Vue({
    el: '#app',

    data: {

        loading: false,

        percent: null,

        spinner: false,

    },

    methods: {

    },

    created() {

        console.log('App created');

        Event.listen('percent', function(percent) {
            console.log('Received Upload Percent Status!');
            this.percent = percent;
        }.bind(this));

        Event.listen('loading_on', function() {
            console.log('Received Loading ON Event!');
            this.loading = true;
        }.bind(this));

        Event.listen('loading_off', function() {
            console.log('Received Loading OFF Event!');
            this.loading = false;
        }.bind(this));

        console.log('Event listeners registered');

    }
});

and heres thge file-management template

<template>
    <div class="file-upload">
        <div class="form-group row">

            <hr>
            <label for="logo" class="control-label"><h2>Add Attachments</h2></label>
             <div class="form-group row">
                <input type="file" multiple="multiple" id="attachments" @change="uploadFieldChange">

                <div class="form-group files">
                    <div class="attachment-holder animated fadeIn" v-cloak v-for="(attachment, index) in attachments">
                        <div class="form-group row">
                            <span class="">{{ attachment.name + ' (' + Number((attachment.size / 1024 / 1024).toFixed(2)) + 'MB)'}}</span>
                            <span v-if="uploadingStatus">Uploading {{ percentCompleted }}%</span>
                            <span v-if="removeButtonVisible" style="background: red; cursor: pointer;" @click="removeAttachment(attachment)"><button class="btn btn-xs btn-danger">Remove</button></span>
                        </div>

                    </div>
                </div>
             </div>
             <button class="btn btn-primary" @click="submit">Upload</button>
        </div>
    </div>
</template>
<script>
    export default {

        props: [
            'settings'
        ],

        data() {

            return {

                // You can store all your files here
                attachments: [],

                messageid: '',

                removeButtonVisible: true,

                uploadingStatus: false,

                // Each file will need to be sent as FormData element
                data: new FormData(),

                percentCompleted: 0,

            }

        },

        watch: {
        },

        computed: {
        },

        methods: {

            validate() {

                if (!this.attachments.length) {
                    toastr.warning('Please add files', 'Warning');
                    return false;
                }

                return true;
            },

            getAttachmentSize() {

                this.upload_size = 0; // Reset to beginningƒ

                this.attachments.map((item) => { this.upload_size += parseInt(item.size); });

                this.upload_size = Number((this.upload_size).toFixed(1));

                this.$forceUpdate();

            },

            prepareFields() {

                for (var i = this.attachments.length - 1; i >= 0; i--) {
                    this.data.append("attachments[][0]", this.attachments[i]);
                }

                this.data.append("messageid", document.getElementById("id").value);

            },

            removeAttachment(attachment) {

                this.attachments.splice(this.attachments.indexOf(attachment), 1);

                this.getAttachmentSize();

            },

            // This function will be called every time you add a file
            uploadFieldChange(e) {

                var files = e.target.files || e.dataTransfer.files;

                if (!files.length)
                    return;

                for (var i = files.length - 1; i >= 0; i--) {
                    if(files[i]['size'] < 10000000) {
                        this.attachments.push(files[i]);
                    } else {
                        console.log(files[i]['name'] + ' ' + files[i]['size'])
                        toastr.warning(files[i]['name'] + ' too large and has been removed', 'Warning');
                    }
                }

                // Reset the form to avoid copying these files multiple times into this.attachments
                document.getElementById("attachments").value = [];

                this.removeButtonVisible = true;

            },

            buttonOn() {
                this.uploadingStatus = true;
            },

            submit() {

                this.prepareFields();

                this.removeButtonVisible = false;

                if (!this.validate()) {
                    return false;
                }

                window.Event.fire('loading_on');

                let self = this;

                var config = {
                    headers: { 'Content-Type': 'multipart/form-data' } ,
                    onUploadProgress: function(progressEvent) {
                        this.percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total );
                        window.Event.fire('percent', this.percentCompleted);
                        this.$forceUpdate();
                    }.bind(this)
                };

                this.uploadingStatus = true;

                // Make HTTP request to store announcement
                axios.post(this.settings.file_management.upload_files, this.data, config)
                .then(function (response) {
                    if (response.data.success) {
                        console.log('Successfull upload');
                        toastr.success('Documents uploaded!', 'Success');
                        this.uploadingStatus = false;
                        this.resetData();
                        window.Event.fire('reload_files'); // Tell AttachmentList component to refresh its list
                    } else {
                        if(response.data.errors == 'validation') {
                            toastr.error(response.data.data + ' - One of your files is an unsupported file type', 'Error');
                        } else if(response.data.errors == 'toobig') {
                            toastr.error(response.data.data + ' - One of your files is bigger than 20Mb', 'Error');
                        } else {
                            toastr.error('Something went a little bit wrong', 'Error');
                        }
                        console.log('Unsuccessful Upload');

                        this.removeButtonVisible = true;
                        this.uploadingStatus = false;
                        this.percentCompleted = 0;
                        this.data = new FormData();
                    }
                    window.Event.fire('loading_off');
                }.bind(this)) // Make sure we bind Vue Component object to this funtion so we get a handle of it in order to call its other methods
                .catch(function (error) {
                    console.log(error);
                    toastr.error('Something went VERY wrong', 'Error');
                    self.removeButtonVisible = true;
                    self.percentCompleted = 0;
                    window.Event.fire('loading_off');

                });

            },

            // We want to clear the FormData object on every upload so we can re-calculate new files again.
            // Keep in mind that we can delete files as well so in the future we will need to keep track of that as well
            resetData() {
                this.data = new FormData(); // Reset it completely
                this.attachments = [];
                this.percentCompleted = 0;
                this.removeButtonVisible = true;
            },

            start() {
                console.log('Starting File Management Component');
            },

        },

        created() {
            this.start();
        }

    }
</script>

Any help pointing out how I've managed the break this would be very much appreciated.

Thanks,

Kris

0 likes
1 reply
krismanning's avatar

Fixed the problem. It was being caused by a div element out of place in the Navbar. Took me ages to find it and no error reported in any browser that gave any sort of clue. Also, same element out of place didnt cause the issue under Bootstrap 3! Go figure.

Please or to participate in this conversation.