skip to Main Content

I have an action class that runs across the entire app which handles file (images) uploads:

class UploadImageAction implements UploadImageContract
{
    public function handle(Request $request, $imageProperty, $image, $imageDir)
    {
        if ($request->hasFile($imageProperty)) {
            // Handle uploading lf_image
            if (!is_null($image) && Storage::exists($image)) {
                // Throw exceptions here
                Storage::delete($image);
            }
            // Throw exceptions here
            return $request->file($imageProperty)->store($imageDir);
        }
    }
}

And I resolve() this class withing the Service class:

public function handleAttachments($request, $report)
    {
        // Handle Attachments
        $uploadImageAction = resolve(UploadImageAction::class);

        // Handle attachment action
        if($request->hasFile('attachment')) {
            $report->attachment = $uploadImageAction->handle($request, 'attachment', $report->attachment, 'reports');
        }

        return $report;
    }

Then passing it to the controller like so:

public function store(ReportsRequest $request, ReportService $reportService)
    {
        try
        {
            $reportService->storeReport($request);
            return redirect('data-entry/reports')->with('success', 'Report Added Successfully');
        }
        catch (ImageUploadException $exception)
        {

        }

Reason for not calling handleAttachment() in the store() is because it’s already passed with the validation within storeReport() method in Service class:

$report->fill($request->validated());
$report = $this->handleAttachments($request, $report);

$report->save();

This functionality works, but sinsce I tried adding Dropzone, that’s where the issue happened.

the url of the dropzone is set like so: url: "{{ route('data-entry.reports.create') }}",. Also tried reports.store instead of .create

This is what I get in laravel debugbar:

enter image description here

and in the dev tools:

enter image description here

JS code:

// set the dropzone container id
    const id = "#kt_dropzonejs_example_2";
    const dropzone = document.querySelector(id);

    // set the preview element template
    var previewNode = dropzone.querySelector(".dropzone-item");
    previewNode.id = "";
    var previewTemplate = previewNode.parentNode.innerHTML;
    previewNode.parentNode.removeChild(previewNode);

    var myDropzone = new Dropzone(id, { // Make the whole body a dropzone
        url: "{{ route('data-entry.reports.create') }}", // Set the url for your upload script location
        parallelUploads: 20,
        previewTemplate: previewTemplate,
        maxFilesize: 1, // Max filesize in MB
        autoQueue: false, // Make sure the files aren't queued until manually added
        previewsContainer: id + " .dropzone-items", // Define the container to display the previews
        clickable: id + " .dropzone-select" // Define the element that should be used as click trigger to select files.
    });

    myDropzone.on("addedfile", function (file) {
        // Hookup the start button
        file.previewElement.querySelector(id + " .dropzone-start").onclick = function () { myDropzone.enqueueFile(file); };
        const dropzoneItems = dropzone.querySelectorAll('.dropzone-item');
        dropzoneItems.forEach(dropzoneItem => {
            dropzoneItem.style.display = '';
        });
        dropzone.querySelector('.dropzone-upload').style.display = "inline-block";
        dropzone.querySelector('.dropzone-remove-all').style.display = "inline-block";
    });

    // Update the total progress bar
    myDropzone.on("totaluploadprogress", function (progress) {
        const progressBars = dropzone.querySelectorAll('.progress-bar');
        progressBars.forEach(progressBar => {
            progressBar.style.width = progress + "%";
        });
    });

    myDropzone.on("sending", function (file) {
        // Show the total progress bar when upload starts
        const progressBars = dropzone.querySelectorAll('.progress-bar');
        progressBars.forEach(progressBar => {
            progressBar.style.opacity = "1";
        });
        // And disable the start button
        file.previewElement.querySelector(id + " .dropzone-start").setAttribute("disabled", "disabled");
    });

    // Hide the total progress bar when nothing's uploading anymore
    myDropzone.on("complete", function (progress) {
        const progressBars = dropzone.querySelectorAll('.dz-complete');

        setTimeout(function () {
            progressBars.forEach(progressBar => {
                progressBar.querySelector('.progress-bar').style.opacity = "0";
                progressBar.querySelector('.progress').style.opacity = "0";
                progressBar.querySelector('.dropzone-start').style.opacity = "0";
            });
        }, 300);
    });

    // Setup the buttons for all transfers
    dropzone.querySelector(".dropzone-upload").addEventListener('click', function () {
        myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
    });

    // Setup the button for remove all files
    dropzone.querySelector(".dropzone-remove-all").addEventListener('click', function () {
        dropzone.querySelector('.dropzone-upload').style.display = "none";
        dropzone.querySelector('.dropzone-remove-all').style.display = "none";
        myDropzone.removeAllFiles(true);
    });

    // On all files completed upload
    myDropzone.on("queuecomplete", function (progress) {
        const uploadIcons = dropzone.querySelectorAll('.dropzone-upload');
        uploadIcons.forEach(uploadIcon => {
            uploadIcon.style.display = "none";
        });
    });

    // On all files removed
    myDropzone.on("removedfile", function (file) {
        if (myDropzone.files.length < 1) {
            dropzone.querySelector('.dropzone-upload').style.display = "none";
            dropzone.querySelector('.dropzone-remove-all').style.display = "none";
        }
    });

2

Answers


  1. Chosen as BEST ANSWER

    I figured out the issue

    Since the image upload field is required, as well as the rest of the form, Dropzone doesn't read the uploaded file since there are some required fields haven't been filled!

    Dropzone actually have a documentation about this: https://docs.dropzone.dev/configuration/tutorials/combine-form-data-with-files

    Since the files are combined with data in the Service class, I need to set autoProcessQueue to false and trigger it with the submit button like myDropzone.processQueue(); once all of the fields are filled to send everything to DB at once.


  2. As set in your route file (in the comment) the post route is named ‘data-entry.reports.store’

    So change the route:

    var myDropzone = new Dropzone(id, { // Make the whole body a dropzone
            url: "{{ route('data-entry.reports.store') }}", // Set the url for your upload script location
            parallelUploads: 20,
            previewTemplate: previewTemplate,
            maxFilesize: 1, // Max filesize in MB
            autoQueue: false, // Make sure the files aren't queued until manually added
            previewsContainer: id + " .dropzone-items", // Define the container to display the previews
            clickable: id + " .dropzone-select" // Define the element that should be used as click trigger to select files.
        });
    

    make sure to clear your route cache using php artisan route:clear

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search