Hello,
You should use dynamic IDs for each Select2 instance and a reusable JavaScript function to initialize Select2 on each dynamically created dropdown. I'll also show you how to wire everything together using Livewire events.
Livewire Component (InvoiceLines.php) First, in your Livewire component, ensure that you have an array ($lines) where each new line added will store an item.
class InvoiceLines extends Component
{
public $lines = [];
public function mount()
{
$this->lines = [
['product_id' => null], // Single line example
];
}
public function addLine()
{
$this->lines[] = ['product_id' => null]; // Add new empty line
}
#[On('productSelected')]
public function productSelected($index, $productId)
{
$this->lines[$index]['product_id'] = $productId; // Update the selected product ID
}
public function render()
{
return view('livewire.invoice-lines');
}
}
``` end PHP
```blade
<div>
<form>
@foreach ($lines as $index => $line)
<div class="line-item">
<select id="productos-{{ $index }}" class="select2" wire:ignore>
<option value="">Select a product</option>
<!-- Add your product options here -->
<option value="1">Product 1</option>
<option value="2">Product 2</option>
<option value="3">Product 3</option>
</select>
</div>
@endforeach
</form>
<button wire:click.prevent="addLine">Add Line</button>
</div>
@push('scripts')
<script>
function initSelect2() {
$('.select2').each(function() {
$(this).select2(); // Initialize select2 for each element
$(this).on('change', function(e) {
let id = $(this).attr('id'); // Get the ID of the select element
let index = id.split('-')[1]; // Extract the index from the ID
// Dispatch Livewire event with the selected value and index
Livewire.dispatch('productSelected', index, $(this).val());
});
});
}
// Reinitialize Select2 after Livewire updates the DOM
document.addEventListener('livewire:load', function () {
initSelect2();
});
document.addEventListener('livewire:update', function () {
initSelect2(); // Re-initialize Select2 after any Livewire update
});
</script>
@endpush
``` end blade