Home > Enterprise >  Strange Activity From Using Two Vue Components inside another Component
Strange Activity From Using Two Vue Components inside another Component

Time:07-27

I am trying to use two different vue components to upload different files inside another vue component. One vue component handles attendance file uploads and the other component handles sales file uploads. They are suppose to download to folders, 'public/upload/attendance' and 'public/upload/sales', respectively.

However, even though the two components are mounting successfully, only one of them is being used. For both of my file uploads the response is "You have successfully uploaded sales file <insert_file_name>". This is the case even though the presence of "Attendance Upload" and "Sales Upload" clearly demonstrate that both components are showing up. Moreover, the success response for the attendance upload should be "You have successfully uploaded attendance file <insert_file_name>".

Here is a picture of what I mean: funky output. The file structure also shows that only the 'upload/sales' route is being used with 'upload/attendance' staying empty: file structure. Does anyone have any advice on tackling this issue? This seems like a strange bug. I am using the two components so that I can easily handle the files that are uploaded in two different locations. Here are my controller and component files, along with the component that they are called inside of as well as the resources/js/app.js and routes/web.php files. Please let me know if you have any advice.

TLDR; I have two similar vue components that are both used in another component. They are almost identical except for their name and where they save files to. However, even though both components are mounting successfully (see console in bottom of first picture), only one of the controllers seems to be in use as file saves to upload/sales instead of upload/attendance and outputs "You have successfully uploaded sales file" instead of "You have successfully uploaded attendance file."

Attendance Upload Controller


namespace App\Http\Controllers;

use Illuminate\Http\Request;

class AttendanceUploadController extends Controller
{
    public function filestoreattendance(Request $request)
    {
        $upload_path = public_path('upload/attendance');
        $file_name = $request->file->getClientOriginalName();
        $generated_new_name = time() . '.' . $request->file->getClientOriginalExtension();
        $request->file->move($upload_path, $file_name);

        return response()->json(['success' => 'You have successfully uploaded attendance file "' . $file_name . '"']);
    }
} 

Sales Upload Controller


namespace App\Http\Controllers;

use Illuminate\Http\Request;

class SalesUploadController extends Controller
{
    public function filestoresales(Request $request)
    {
        $upload_path = public_path('upload/sales');
        $file_name = $request->file->getClientOriginalName();
        $generated_new_name = time() . '.' . $request->file->getClientOriginalExtension();
        $request->file->move($upload_path, $file_name);

        return response()->json(['success' => 'You have successfully uploaded sales file "' . $file_name . '"']);
    }
}

AttendanceUpload.vue

<template>
    <div  style="margin-top: 50px;">
        <div >
            <h4>Attendance Upload</h4><br>
            <div style="max-width: 500px; margin: 0 auto;">
                <div v-if="success !== ''"  role="alert">
                    {{success}}
                </div>
                <form @submit="submitForm" enctype="multipart/form-data">
                    <div >
                        <div >
                            <input type="file" name="filename"  id="inputFileUpload"
                                   v-on:change="onFileChange">
                            <label  for="inputFileUpload">Choose file</label>
                        </div>
                        <div >
                            <input type="submit"  value="Upload">
                        </div>
                    </div>
                    <br>
                    <p >{{filename}}</p>
                </form>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('Component 1 successfully mounted.')
        },
        data() {
            return {
                filename: '',
                file: '',
                success: ''
            };
        },
        methods: {
            onFileChange(e) {
                //console.log(e.target.files[0]);
                this.filename = "Selected File: "   e.target.files[0].name;
                this.file = e.target.files[0];
            },
            submitForm(e) {
                e.preventDefault();
                let currentObj = this;
                const config = {
                    headers: {
                        'content-type': 'multipart/form-data',
                        'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
                    }
                }

                // form data
                let formData = new FormData();
                formData.append('file', this.file);

                // send upload request
                axios.post('/store_file', formData, config)
                    .then(function (response) {
                        currentObj.success = response.data.success;
                        currentObj.filename = "";
                    })
                    .catch(function (error) {
                        currentObj.output = error;
                    });
            }
        }
    }
</script>

SalesUpload.vue

<template>
    <div  style="margin-top: 50px;">
        <div >
            <h4>Sales Upload</h4><br>
            <div style="max-width: 500px; margin: 0 auto;">
                <div v-if="success !== ''"  role="alert">
                    {{success}}
                </div>
                <form @submit="submitForm" enctype="multipart/form-data">
                    <div >
                        <div >
                            <input type="file" name="filename"  id="inputFileUpload"
                                   v-on:change="onFileChange">
                            <label  for="inputFileUpload">Choose file</label>
                        </div>
                        <div >
                            <input type="submit"  value="Upload">
                        </div>
                    </div>
                    <br>
                    <p >{{filename}}</p>
                </form>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('Component 2 successfully mounted.')
        },
        data() {
            return {
                filename: '',
                file: '',
                success: ''
            };
        },
        methods: {
            onFileChange(e) {
                //console.log(e.target.files[0]);
                this.filename = "Selected File: "   e.target.files[0].name;
                this.file = e.target.files[0];
            },
            submitForm(e) {
                e.preventDefault();
                let currentObj = this;
                const config = {
                    headers: {
                        'content-type': 'multipart/form-data',
                        'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
                    }
                }

                // form data
                let formData = new FormData();
                formData.append('file', this.file);

                // send upload request
                axios.post('/store_file', formData, config)
                    .then(function (response) {
                        currentObj.success = response.data.success;
                        currentObj.filename = "";
                    })
                    .catch(function (error) {
                        currentObj.output = error;
                    });
            }
        }
    }
</script>

Component that calls the above two components:

<template>
    <div v-if="errors">
    <div v-for="(v, k) in errors" :key="k" >
    <p v-for="error in v" :key="error" >
      {{ error }}
    </p>
    </div>
    </div>

    <form  @submit.prevent="saveInvoice" enctype="multipart/form-data">
        <div >
            <div>
                <label for="venue" >Venue</label>
                <div >
                    <input type="text" name="venue" id="venue"
                           
                           v-model="form.venue">
                </div>
            </div>

            <div>
                <label for="generalmanager" >General Manager</label>
                <div >
                    <input type="text" name="generalmanager" id="generalmanager"
                           
                           v-model="form.generalmanager">
                </div>
            </div>

            <div>
                <label for="eventtitle" >Event Title</label>
                <div >
                    <input type="text" name="eventtitle" id="eventtitle"
                           
                           v-model="form.eventtitle">
                </div>
            </div>
            <div>
                <label for="eventdate" >Event Date</label>
                <div >
                    <input type="text" name="eventdate" id="eventdate"
                           
                           v-model="form.eventdate">
                </div>
            </div>
            <div>
                <label >Attendance file</label>
                    <AttendanceUpload></AttendanceUpload>
            </div>
            <div>
                <label >Sales file</label>
                    <SalesUpload></SalesUpload>
            </div>
        </div>

        <button type="submit"
                >
            Create
        </button>
    </form>
</template>

<script>
import { reactive } from 'vue'
import useInvoices from '../../composables/invoices'
import AttendanceUpload from "../AttendanceUpload.vue";
import SalesUpload from "../SalesUpload.vue";


export default {
    setup() {
        const form = reactive({
            venue: '',
            generalmanager: '',
            eventtitle: '',
            eventdate: '',
            attendance: ''
        })

        const { errors, storeInvoice } = useInvoices()

        const saveInvoice = async () => {
            await storeInvoice({ ...form });
        }

        
        return {
            form,
            errors,
            saveInvoice
        }
    },
    components: { AttendanceUpload, SalesUpload }
}
</script>

resources/js/app.js

require('./bootstrap');

require('alpinejs');

import { createApp } from 'vue';
import router from './router'
import InvoicesIndex from './components/invoices/InvoicesIndex';
import AttendanceUpload from './components/AttendanceUpload';
import SalesUpload from './components/SalesUpload';




createApp({
    components: {
        InvoicesIndex,
        AttendanceUpload,
        SalesUpload
        
    }
}).use(router).mount('#app')

routes/web.php

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\FileUploadController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth'])->name('dashboard');

require __DIR__.'/auth.php';

Route::view('/{any}', 'dashboard')
    ->middleware(['auth'])
    ->where('any', '.*');

Route::get('upload_file', function () {
   return view('dashboard');
});

Route::post('store_file', 'App\Http\Controllers\AttendanceUploadController@filestoreattendance');
Route::post('store_file', 'App\Http\Controllers\SalesUploadController@filestoresales');

CodePudding user response:

I'm certainly not a Laravel pro, but in your routes/web.php file both of your routes for file uploads seem to have the same name, which may be causing it to only use the one that was defined last.

routes/web.php

Route::post('store_file', 'App\Http\Controllers\AttendanceUploadController@filestoreattendance');
Route::post('store_file', 'App\Http\Controllers\SalesUploadController@filestoresales');

Try changing the routes in the above file, to something like "store_attendance_file" and "store_sales_file" and update the POST routes in the axios calls in your file upload components to reflect these changes

  • Related