I am having some trouble with updating a list of items, where the array is stored, and I can call it into a foreach loop to render out paragraph elements, but every time an item is added to the array, it keeps the elements that are already rendered, and adds the full, updated list to it. Is there a good way to refresh just that part of the DOM to show only what's currently in the list, and not stack it? I looked at the "Troubleshooting" page of the Livewire docs, but I'm not sure how the wire:key="name" thing works, or if it will work in this case. Weirdly, not a lot of information about it. I had considered using a child component, but I can't seem to get that to work correctly.
I have looked over Google quite a few times, but haven't had luck finding anything useful.
The code is a bit long, but hopefully it makes sense. Also, I'm still very new to this, so it's probably not the most optimal solution for what I want to accomplish.
TagSearchBar.php
<?php
namespace App\Http\Livewire;
use App\Models\Tag;
use Livewire\Component;
class TagSearchBar extends Component
{
public $tagQuery;
public $tagResult;
public $tagSelected;
public $tagSelectedList;
protected $listeners = [
'tagListUpdated' => 'updatedTagSelected'
];
public function mount()
{
$this->resetSearch();
$this->tagSelected = [];
$this->tagSelectedList = [];
}
public function resetSearch()
{
$this->tagQuery = '';
$this->tagResult = [];
}
public function updatedTagQuery()
{
$this->tagResult = Tag::where('alias', 'like', '%' . $this->tagQuery . '%')
->take(25)->get()->toArray();
}
public function addToTagList($tagId)
{
$this->tagSelected[] = $tagId;
$this->emit('tagListUpdated');
}
public function updatedTagSelected()
{
foreach ($this->tagSelected as $tagId)
{
$this->tagSelectedList[] = Tag::find($tagId);
}
$this->render();
}
public function render()
{
return view('livewire.tag-search-bar', [
'tags' => Tag::all(),
]);
}
}
tag-search-bar.blade.php
<div class="tag-search-container relative">
<div class="selectedTags">
@foreach ($tagSelectedList as $selectedTag)
<p
class="tag-{{ $selectedTag['type'] }} tag-pill"
title="{{ $selectedTag['type'] }}: {{ $selectedTag['slug'] }}"
wire:click="removeFromTagList({{ $selectedTag['id'] }})"
>
{{ $selectedTag['alias'] }}
</p>
@endforeach
</div>
<input
type="text"
placeholder="Add tags..."
value=''
wire:model.debounce.500ms="tagQuery"
wire:keydown.escape="resetSearch"
>
@if(!empty($tagQuery))
<div class="tag-list-container absolute">
@if(!empty($tagResult))
@foreach($tagResult as $tag)
<p
class="tag-{{ $tag['type'] }} tag-pill"
title="{{ $tag['type'] }}: {{ $tag['slug'] }}"
wire:click="addToTagList({{ $tag['id'] }})"
>
{{ $tag['alias'] }}
</p>
@endforeach
@else
<p>Add new tag?</p>
<livewire:new-tag>
@endif
</div>
@endif
</div>
In short, all of this code functions as intended, except the first foreach loop area. It renders the elements, but just stacks when updated. The code is also not complete, I have to add ways of preventing duplicates, and a remove function, I'm not worried about that right now.