Foks's avatar
Level 15

Selected image always null

Hello! I'm trying to make a feature where the users can upload images to a recipe, however, it seems like the selected image is always null. The end goal is to use Spatie's Laravel-Media-library to handle the images for the recipes.

RecipeFileUpload.php

<?php

namespace App\Http\Livewire;

use App\Models\Recipe;
use Livewire\Component;
use Livewire\WithFileUploads;

class RecipeFileUpload extends Component
{
    use WithFileUploads;

    public $recipe;
    public $photo;

    /**
     * Mount the component.
     *
     * @param Recipe $recipe
     * @return void
     */
    public function mount(Recipe $recipe)
    {
        $this->recipe = $recipe;
    }

    public function savePhoto()
    {
        $this->resetErrorBag();
        $this->photo->store('photos');
        //dd($this->photo);
        //$this->recipe->addMedia($this->photo);

        $this->emit('saved');
    }

    public function render()
    {
        return view('livewire.recipe-file-upload');
    }
}

recipe-file-upload.blade.php

<div>

    <div class="md:grid md:grid-cols-3 md:gap-6">
        <x-jet-section-title>
            <x-slot name="title">Medier</x-slot>
            <x-slot name="description">Lorem ipsum</x-slot>
        </x-jet-section-title>

        <div class="mt-5 md:mt-0 md:col-span-2">
            <form id="form" wire:submit.prevent="savePhoto" enctype="multipart/form-data">
                <div class="px-4 py-5 bg-white sm:p-6 shadow sm:rounded-tl-md sm:rounded-tr-md">
                <div class="grid grid-cols-6 gap-6">
                    <!--<div class="mt-1 flex items-center col-span-6">
                        <div class="mt-1 w-full flex justify-center px-6 pt-5 pb-6 border-2 border-gray-300 border-dashed rounded-md">
                            <div class="space-y-1 text-center">
                                <svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none" viewBox="0 0 48 48" aria-hidden="true">
                                    <path d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
                                </svg>
                                <div class="flex text-sm text-gray-600">
                                    <label for="photo" class="relative cursor-pointer bg-white rounded-md font-medium text-indigo-600 hover:text-indigo-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-indigo-500">
                                        <span>Upload a file</span>
                                        <input id="photo" name="photo" type="file" wire:model="photo" class="sr-only">
                                    </label>
                                    <p class="pl-1">or drag and drop</p>
                                </div>
                                <p class="text-xs text-gray-500">
                                    PNG, JPG, GIF up to 10MB
                                </p>
                            </div>
                        </div>
                    </div>-->

                    <div x-data="{photoPreview: null}" class="col-span-6 sm:col-span-4">

                        <input type="file" class="hidden"
                               wire:model="photo"
                               x-ref="photo"
                               x-on:change="
                                    photoName = $refs.photo.files[0].name;
                                    const reader = new FileReader();
                                    reader.onload = (e) => {
                                        photoPreview = e.target.result;
                                    };
                                    reader.readAsDataURL($refs.photo.files[0]);
                            " />

                        <x-jet-label for="photo" value="{{ __('Photo') }}" />


                        <div class="mt-2" x-show="photoPreview">
                            <span class="block rounded-full w-20 h-20"
                                  x-bind:style="'background-size: cover; background-repeat: no-repeat; background-position: center center; background-image: url(\'' + photoPreview + '\');'">
                            </span>
                        </div>

                        <x-jet-secondary-button class="mt-2 mr-2" type="button" x-on:click.prevent="$refs.photo.click()">
                            {{ __('Select A New Photo') }}
                        </x-jet-secondary-button>

                        <x-jet-input-error for="photo" class="mt-2" />
                    </div>

                    </div>
                </div>

                <div class="flex items-center justify-end px-4 py-3 bg-gray-50 text-right sm:px-6 shadow sm:rounded-bl-md sm:rounded-br-md">
                    <x-jet-action-message class="mr-3" on="created">
                        {{ __('Tilføjet.') }}
                    </x-jet-action-message>

                    <x-jet-button>
                        {{ __('Gem') }}
                    </x-jet-button>
                </div>
            </form>
        </div>
    </div>


@if ($this->recipe->tasks->isNotEmpty())
        <x-jet-section-border></x-jet-section-border>

        <!-- Manage API Tokens -->
        <div class="mt-5 sm:mt-0">
            <x-jet-action-section>
                <x-slot name="title">
                    {{ __('Organiser trin') }}
                </x-slot>

                <x-slot name="description">
                    {{ __('lorem ipsum') }}
                </x-slot>

                <!-- API Token List -->
                <x-slot name="content">
                    <div class="space-y-6">
                        @foreach ($this->recipe->tasks as $task)
                            <div class="flex items-center justify-between">
                                <div>
                                    {{ $task->title }}
                                </div>

                                <div class="flex items-center">
                                    <div class="text-sm text-gray-400">
                                        {{ __('Last used') }}
                                    </div>

                                    <button class="cursor-pointer ml-6 text-sm text-gray-400 underline" wire:click="manageRecipeTask({{ $task->id }})">
                                        {{ __('Rediger') }}
                                    </button>

                                    <button class="cursor-pointer ml-6 text-sm text-red-500" wire:click="confirmRecipeTaskDeletion({{ $task->id }})">
                                        {{ __('Fjern') }}
                                    </button>
                                </div>
                            </div>
                        @endforeach
                    </div>
                </x-slot>
            </x-jet-action-section>
        </div>
    @endif
</div>

Any clues as to why this happens?

The file I'm trying to load is called image.png

0 likes
3 replies
Snapey's avatar

start with the basics as per the Livewire docs. Not sure why you are using alpine to preview the image?

Foks's avatar
Level 15

@snapey I did start with the basics from Livewire docs, however, it didn't work. I found it was due to my browser actually blocking the request, I changed browsers and it worked, sort of. Since I'm using Laravel Sail I'm running my own MinIO instance in docker, but I can't seem to be allowed to upload files to it.

My .env file. I copied what the Laravel docs said I should have. However, it didn't even try to connect to the default AWS_ENDPOINT value, so I changed it to https://localhost:9000 and now Sail is trying is receiving a 404.

FILESYSTEM_DRIVER=s3
AWS_ACCESS_KEY_ID=sail
AWS_SECRET_ACCESS_KEY=password
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=local
AWS_ENDPOINT=http://localhost:9000
AWS_USE_PATH_STYLE_ENDPOINT=true

Image of the request: https://i.imgur.com/aLWaufv.png

Snapey's avatar
Snapey
Best Answer
Level 122

Its a while since I uploaded direct to S3 but I remember having cors issues. Your setup seems a little more complicated.

I would make sure you can save a file to aws with tinker to start with. Your details (such as the bucket name) seem suspect

1 like

Please or to participate in this conversation.