skip to Main Content

I am using browser-image-compression library to compress the images before uploading. Now it gives the compressed Image and the compressed image is also stored in the storage folder.

But I want to display the uploaded attachment as soon as the image is uploaded. I tried to dd($this->uploaded_cost_attachments) in component and it gives response there but when I try to <div>@dump($uploaded_cost_attachments)</div> It is always empty.

**
Livewire Component:**

public $cost_attachments = [];
public $uploaded_cost_attachments = [];
public function updatedCostAttachments()
 {
    $this->validate([
      'cost_attachments.*' => 'file|mimes:jpg,png,pdf,xls,xlsx',
    ]);

    if ($this->cost_attachments) {
      foreach ($this->cost_attachments as $file) {
                
         $filePath = $file->store('cost_attachments', 'public');

         $this->uploaded_cost_attachments[] = [
             'file' => $filePath,
              'id' => null,
         ];
     }
   }
 }

Blade.php:

<div class="mt-2">
   <div class="relative">
      <input onchange="handleImageUpload(event);" type="file" multiple id="file-input" />
                                                
    </div>
</div>

<div class="mt-2">
    @foreach($uploaded_cost_attachments as $key => $file)
        <span class="inline-flex items-center gap-x-1.5 rounded-md px-2 py-1 text-xs font-medium 
            text-gray-900 ring-1 ring-inset ring-gray-200">
        <svg wire:click="removeCostAttachment({{ $key }})" xmlns="http://www.w3.org/2000/svg" 
             viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5 cursor-pointer">
             <path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 
                    11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 
                    8.94 6.28 5.22z" />
        </svg>
        <a target="_blank" href="{{ asset('storage/'.$file['file']) }}">
            ...{{ substr($file['file'], -10) }}
        </a>
        </span>
    @endforeach
</div>


<script>
    // Image compression
        async function handleImageUpload(event) {

            const files = event.target.files;

            const options = {
                maxSizeMB: 2,
                maxWidthOrHeight: 1920,
                useWebWorker: true,
            }
            for (const file of files) {
                const fileType = file.type;

                if (fileType === "application/pdf") {
                    // Handle PDF upload without compression
                    console.log('PDF File:', file.name);

                    // Upload the PDF file directly without compression
                    @this.upload('cost_attachments', file, (uploadedFilename) => {
                        console.log('PDF uploaded:', uploadedFilename);
                    }, (error) => {
                        console.error('Upload error:', error);
                    }, (event) => {
                        console.log('Upload progress:', event.detail.progress);
                    });

                } else if (fileType.startsWith('image/')) {
                    try {
                        // Compress images
                        const compressedFile = await imageCompression(file, options);
                        console.log('Compressed Image:', compressedFile.name);
                        console.log(`Compressed size: ${compressedFile.size / 1024 / 1024} MB`);

                        // Upload the compressed image
                        @this.upload('cost_attachments', compressedFile, (uploadedFilename) => {
                            console.log('Image uploaded:', uploadedFilename);
                        }, (error) => {
                            console.error('Upload error:', error);
                        }, (event) => {
                            console.log('Upload progress:', event.detail.progress);
                        });

                    } catch (error) {
                        console.error('Image compression error:', error);
                    }
                } else {
                    console.error('Unsupported file type:', fileType);
                }
            }


        }
</script>

I am using the input without wire:model, following this answer on github.

2

Answers


  1. Chosen as BEST ANSWER

    Finally I solved it by emiting an event from component when the files are uploaded and then when I listen the event in blade I update the uploaded_cost_attachments array with updated array I received in event.

    public function costAttachments()
        {
            $this->validate([
                'cost_attachments.*' => 'file|mimes:jpg,png,pdf,xls,xlsx',
            ]);
    
            if ($this->cost_attachments) {
                foreach ($this->cost_attachments as $file) {
                    $filePath = $file->store('cost_attachments', 'public');
                    $this->uploaded_cost_attachments[] = [
                        'file' => $filePath,
                        'id' => null,
                    ];
                }
                $this->emit('fileUploaded', $this->uploaded_cost_attachments);
                $this->cost_attachments = [];
            }
        }
    

    and in blade:

    document.addEventListener('livewire:load', function() {
        Livewire.on('fileUploaded', function(array) {
            @this.set('uploaded_cost_attachments', array);
        });
    });
    

    by doing this now the array uploaded_cost_attachments get updated and display the attachments.


  2. Your code seems to be right but attachemet is not refreshed when it’s render to view file
    please update in your file js code you can refresh the component by using this

    @this.call('refreshAttachments'); 
    

    in the @this.upload , upload the compress image

    and mount this to your livewire Component like this after the updatedCostAttachments() function

    public function refreshAttachments()
    {
        $this->uploaded_cost_attachments = $this->uploaded_cost_attachments;
    }
    

    by this approach this can solve your problem

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