skip to Main Content

I have a list of tasks that are each editable and have an image upload component. but if i upload an image in any of the components that aren’t the first in the list it still renders in the first component. Also i use the spatie mediaLibrary for my image uploads.

livewire components:

ShiftShow

<?php

namespace AppHttpLivewireAppShift;

use AppModelsCompany;
use AppModelsShift;
use LivewireComponent;

class ShiftShow extends Component
{
    public Shift $shift;
    public Company $company;
    public $tasks;
    public $return_link;

    protected $listeners = ['pullTasks', 'refreshComponent' => '$refresh'];

    public function mount() 
    {
        $this->company = $this->shift->company;
        $this->return_link = route('company.dashboard');
        
    }

    public function pullTasks()
    {
        $this->tasks = $this->shift->tasks()->get();
    }

    public function render()
    {
        $this->pullTasks();
        return view('livewire.app.shift.shift-show')->layout('layouts.app', ['company' =>     $this->company, 'title' => 'Dienst']);
    }
}

TaskItem

<?php

namespace AppHttpLivewireAppShift;

use AppEnumsTaskStatusEnum;
use AppModelsTask;
use AppTraitsTimetrait;
use LivewireComponent;
use LivewireWithFileUploads;

class TaskItem extends Component
{
    use Timetrait, WithFileUploads;

    public Task $task;
    public $description;
    public $status_item;
    public $task_status;
    public $status;
    public $active;
    public $file;
    public $associated_file;

    public function mount()
    {
        $this->active = $this->checkIfCurrent($this->task->shift);
        $this->status_item = TaskStatusEnum::getValues();
        $this->description = $this->task->description;
        $this->task_status = $this->task->status;
    
        $this->associated_file = $this->task->getMedia();
    }

    public function save()
    {
        $this->task->update([
            'description' => $this->description,
            'status' => $this->task_status,
            'finished_at' => now(),
        ]);
        if(!is_null($this->file))
        {
            $this->task
            ->addMedia($this->file)
            ->toMediaCollection();
            $this->file = null;
            $this->associated_file = $this->task->getMedia();
        }
        $this->emit('pullTasks');
        $this->emit('refreshComponent');
    }
    
    public function render()
    {
        $this->status = $this->task->status;

        return view('livewire.app.shift.task-item');
    }
}

corresponding blade components

shiftshow blade

<div>
    <a href="{{route('company.dashboard')}}" type="button" >
        <div class="inline-flex lg:ml-7 mb-2 rounded-full bg-indigo-600 dark:bg-gray-500 p-2 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
                <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" />
            </svg>
        </div>
    </a>
    <x-base-container return_link="$return_link" >
        <div class="border-b border-gray-200 bg-white dark:bg-gray-900 px-4 py-5 sm:px-6">
            <h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">{{$shift->title}}</h3>
        </div>
        <ul role="list" class="divide-y divide-white/5">
            @foreach($tasks as $i => $task)
                <livewire:app.shift.task-item wire:key="task-{{$task->id}}" :task="$task">
            @endforeach
        </ul>
    </x-base-container>
</div>

taskitem blade

<div x-data="{expanded: false}"  x-on:click.outside="expanded == true ? expanded = false : expanded = false">
  <li class="relative flex items-center space-x-4 py-4">
      <div class="min-w-0 flex-auto" >
        <div class="flex items-center gap-x-3" @if($active) x-on:click="expanded = ! expanded" @endif>
          <div class="flex-none rounded-full p-1 {{$status === 'not_done' ?
            'text-gray-500 bg-gray-100/10' : ($status === 'done' ? 'text-green-500 bg-green-100/10' : 'text-red-500 bg-red-100/10')}}">
            <div class="h-2 w-2 rounded-full bg-current"></div>
          </div>
          <h2 class="min-w-0 text-sm font-semibold leading-6 dark:text-white">
            <div class="flex gap-x-2">
              <span class="truncate">{{$task->title}}</span>
            </div>
          </h2>
          <div class="ml-auto" >
              <svg x-show="expanded"  class="h-5 w-5 flex-none text-gray-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 15.75l7.5-7.5 7.5 7.5" />
              </svg>              
              <svg x-show="!expanded" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-5 w-5 flex-none text-gray-400">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
              </svg>
          </div>
        </div>
      </div>
  </li>
  @if($active)
  <div  class="lg:flex lg:flex-col" x-show="expanded" wire:key='task_item-{{$task->id}}'>
    <div class="mr-auto mb-5">
      <label for="location" class="block text-sm font-medium leading-6 dark:text-white text-gray-900">Status</label>
      <select id="location" wire:model="task_status" name="location" class="mt-2 block w-full rounded-md border-0 py-1.5 pl-3 pr-10 dark:text-white dark:bg-gray-800 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-indigo-600 sm:text-sm sm:leading-6">
        @foreach($status_item as $item)
          <option value="{{$item}}">{{__('status.task.'.$item)}}</option>
        @endforeach
      </select>
    </div>
    <textarea wire:model='description' placeholder="Bijzonderdheden" name="" id="" cols="30" rows="10" class="dark:bg-gray-800 text-white resize-none w-full lg:w-64"></textarea>
    @if(count($associated_file) == 0)
    <label for="picture" class="px-4 py-2 dark:bg-gray-700 bg-gray-200 mr-auto rounded-md mt-2 flex w-fit">
      <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5 mr-2">
        <path stroke-linecap="round" stroke-linejoin="round" d="M6.827 6.175A2.31 2.31 0    015.186 7.23c-.38.054-.757.112-1.134.175C2.999 7.58 2.25 8.507 2.25 9.574V18a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9.574c0-1.067-.75-1.994-1.802-2.169a47.865 47.865 0 00-1.134-.175 2.31 2.31 0 01-1.64-1.055l-.822-1.316a2.192 2.192 0 00-1.736-1.039 48.774 48.774 0 00-5.232 0 2.192 2.192 0 00-1.736 1.039l-.821 1.316z" />
        <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 12.75a4.5 4.5 0 11-9 0 4.5 4.5 0 019 0zM18.75 10.5h.008v.008h-.008V10.5z" />
      </svg>
      Upload
    </label>
    @endif
    <div wire:key='image_element-{{$task->id}}'>
      @if($file)
        <div class="flex">
          <img src="{{ $file->temporaryUrl() }}" alt="" class="w-16 h-24 mt-2">
          <span class="ml-2 mt-auto">{{$file->getFileName()}}</span>
        </div>
      @endif
      @if(count($associated_file) > 0)
        <div class="flex">
          <img src="{{ $associated_file[0]->getUrl() }}" alt="" class="w-16 h-24 mt-2">          
        </div>
      @endif
      <input type="file" name="picture" id="picture" accept="image/*" wire:model="file" class="hidden">
    </div>
    <x-primary-button class="mr-auto mt-5 mb-2" wire:click="save" x-on:click="expanded = false">Opslaan</x-primary-button>
  </div>
  @endif
</div>

I tried adding extra wire keys to each component to try and force the image to show in the correct component but it still only renders in the first.

2

Answers


  1. Chosen as BEST ANSWER

    Problem is fixed after alot of searching i found that i needed to add id="{{'picture-'.$task->id}}" to the input the same to the label for to make this implementation work.


  2. you forget to add ":"

     :wire:key=""
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search