Hello, I’m working with two Livewire components in Laravel, where I want the parent component (FakturBarang) to listen for an event dispatched from the child component (TambahFakturBarang) after successfully adding data.
I have tried using #[On('updateFakturBarang')] in the parent component and dispatch('updateFakturBarang') in the child component, but the event in the parent component is not being triggered when I dispatch it.
Here’s the code in the parent component (FakturBarang):
<?php
namespace App\Livewire\Persediaan\Faktur;
use Carbon\Carbon;
use Livewire\Component;
use Livewire\Attributes\On;
use Livewire\Attributes\Title;
use App\Helpers\ServicesPersediaan;
class FakturBarang extends Component
{
#[Title('Tess | Faktur-Barang')]
public $idFaktur;
public $fakturBarang;
private ServicesPersediaan $servicesPersediaan;
#[On('updateFakturBarang')]
public function updateFakturBarang()
{
dd('tes');
$this->fakturBarang = $this->getFakturBarang();
}
public function boot(ServicesPersediaan $servicesPersediaan)
{
$this->servicesPersediaan = $servicesPersediaan;
}
public function mount($id = null)
{
$this->idFaktur = $id;
$this->fakturBarang = $this->getFakturBarang();
}
public function render()
{
if ($this->idFaktur) {
return $this->renderDetailFaktur();
}
return $this->renderFakturBarang();
}
public function renderDetailFaktur()
{
return view('livewire.persediaan.faktur.detail-faktur', [
'idFaktur' => $this->idFaktur
]);
}
public function renderFakturBarang()
{
return view('livewire.persediaan.faktur.faktur-barang', [
'fakturBarang' => $this->fakturBarang
]);
}
public function getFakturBarang()
{
$tahunAnggaran = date('Y');
$kodeUnit = 22;
$response = $this->servicesPersediaan->getFakturBarang($kodeUnit, $tahunAnggaran);
if (!is_array($response) || !isset($response['success']) || !$response['success']) {
return [];
}
// ubah format tanggal
foreach ($response['data'] as $key => $value) {
$response['data'][$key]['date'] = Carbon::parse($value['date'])->translatedFormat('d F Y');
}
return $response['data'];
}
}
and this in child component (TambahFakturBarang):
<?php
namespace App\Livewire\Persediaan\Forms\FakturBarang;
use Livewire\Component;
use App\Helpers\DateHelper;
use Livewire\Attributes\Validate;
use App\Helpers\ServicesPersediaan;
use Illuminate\Support\Facades\Log;
class TambahFakturBarang extends Component
{
#[Validate]
public $tanggalFaktur = '';
public $nomorFaktur = '';
public $akunBelanja = [];
public $selectedAkunBelanja = null;
private ServicesPersediaan $servicesPersediaan;
public function boot(ServicesPersediaan $servicesPersediaan)
{
$this->servicesPersediaan = $servicesPersediaan;
}
public function mount()
{
$this->akunBelanja = $this->getAkunBelanja();
}
public function rules()
{
return [
'tanggalFaktur' => 'required',
'nomorFaktur' => 'required',
'selectedAkunBelanja' => 'required',
];
}
public function messages()
{
return [
'tanggalFaktur.required' => 'Tanggal Faktur tidak boleh kosong',
'nomorFaktur.required' => 'Nomor Faktur tidak boleh kosong',
'selectedAkunBelanja.required' => 'Akun Belanja tidak boleh kosong',
];
}
public function store()
{
$this->validate();
$this->tanggalFaktur = DateHelper::convertToYMD($this->tanggalFaktur);
$tahunAnggaran = date('Y');
$unitKerja = 22;
$data = [
'homebaseId' => $unitKerja,
'stockAccountId' => $this->selectedAkunBelanja,
'year' => $tahunAnggaran,
'number' => $this->nomorFaktur,
'date' => $this->tanggalFaktur,
];
$response = $this->servicesPersediaan->postFakturBarang($data);
if (isset($response['success']) && $response['success'] == true) {
$this->reset();
Log::info('Faktur Barang berhasil ditambahkan', ['response' => $response]);
$this->dispatch('toast', [
'title' => 'Berhasil!',
'message' => 'Faktur barang berhasil ditambahkan.',
'type' => 'success',
]);
$this->dispatch('updateFakturBarang');
$this->dispatch('closeModal');
} else {
$this->reset();
Log::error('Faktur Barang gagal ditambahkan', ['response' => $response]);
$this->dispatch('toast', [
'title' => 'Gagal!',
'message' => 'Faktur barang gagal ditambahkan. Silahkan coba lagi.',
'type' => 'error',
]);
$this->dispatch('closeModal');
}
}
public function render()
{
return view('livewire.persediaan.forms.faktur-barang.tambah-faktur-barang', [
'akunBelanja' => $this->akunBelanja,
]);
}
public function getAkunBelanja()
{
$response = $this->servicesPersediaan->getAkunBelanja();
if (!is_array($response) || !isset($response['success']) || !$response['success']) {
return [];
}
return $response['data'];
}
}
In the blade faktur-barang.blade.php:
@extends('layouts.persediaan-layout')
@php
$breadcrumbs = [
['name' => 'Home', 'url' => route('dashboard-persediaan'), 'icon' => 'heroicon-o-home'],
['name' => 'Faktur Barang', 'icon' => 'fas-receipt'],
];
@endphp
@section('page-title', 'Daftar Faktur')
@section('persediaan-content')
<div>
{{-- tambah faktur --}}
<button type="button"
class="inline-flex items-center px-3 py-2 text-sm font-medium text-white transition border border-transparent rounded-lg bg-green-dark gap-x-2 hover:bg-green focus:outline-none disabled:opacity-50 disabled:pointer-events-none"
aria-haspopup="dialog" aria-expanded="false" aria-controls="modal-tambah-faktur-barang"
data-hs-overlay="#modal-tambah-faktur-barang">
<x-ri-add-fill class="size-6" />
Tambah Faktur Barang
</button>
<table>
<thead>
<tr>
<th>No</th>
<th>Unit Kerja</th>
<th>Kode Akun</th>
<th>No Faktur</th>
<th>Tgl Faktur</th>
<th>Nilai Faktur</th>
<th>No SPP</th>
<th>No SPM</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach ($fakturBarang as $faktur)
<tr wire:key='{{ $faktur['id'] }}'>
<td>{{ $loop->iteration }}</td>
<td>UPT TIK</td>
<td>{{ $faktur['stockAccountId'] }}</td>
<td>{{ $faktur['number'] }}</td>
<td>{{ $faktur['date'] }}</td>
<td>{{ $faktur['totalPrice'] }}</td>
<td>{{ $faktur['status'] }}</td>
<td>{{ $faktur['status'] }}</td>
<td>
<a href="{{ route('faktur-barang.detail', ['id' => $faktur['id']]) }}">Lihat</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<livewire:persediaan.forms.faktur-barang.tambah-faktur-barang />
@endsection
and tambah-faktur-barang.blade.php:
<x-modal id="modal-tambah-faktur-barang" :submitAction="'store'" :header="'Input Faktur Barang'" :overlay="'modal-tambah-faktur-barang'">
<x-slot:body>
<div class="max-w-lg space-y-4">
{{-- TAHUN ANGGARAN --}}
<div>
<label for="tahunAnggaran" class="block mb-2 text-sm font-medium">Tahun Anggaran</label>
<div wire:ignore class="relative">
<select id="tahunAnggaran"
data-hs-select='{
"placeholder": "Select option...",
"toggleTag": "<button type=\"button\" aria-expanded=\"false\"></button>",
"toggleClasses": "hs-select-disabled:pointer-events-none hs-select-disabled:opacity-50 relative py-3 ps-4 pe-9 flex gap-x-2 text-nowrap w-full cursor-pointer bg-white border border-gray-200 rounded-lg text-start text-sm focus:outline-none focus:ring-2 focus:ring-green",
"dropdownClasses": "mt-2 z-50 w-full max-h-72 p-1 space-y-0.5 bg-white border border-gray-200 rounded-lg overflow-hidden overflow-y-auto [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-track]:bg-gray-100 [&::-webkit-scrollbar-thumb]:bg-gray-300 dark:[&::-webkit-scrollbar-track]:bg-neutral-700 dark:[&::-webkit-scrollbar-thumb]:bg-neutral-500 dark:bg-neutral-900 dark:border-neutral-700",
"optionClasses": "py-2 px-4 w-full text-sm text-gray-800 cursor-pointer hover:bg-gray-50 rounded-lg focus:outline-none focus:bg-gray-100 hs-select-disabled:pointer-events-none hs-select-disabled:opacity-50",
"optionTemplate": "<div class=\"flex justify-between items-center w-full\"><span data-title></span><span class=\"hidden hs-selected:block\"><svg class=\"shrink-0 size-3.5 text-blue-600\" xmlns=\"http:.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg></span></div>",
"extraMarkup": "<div class=\"absolute top-1/2 end-3 -translate-y-1/2\"><svg class=\"shrink-0 size-3.5 text-gray-500 dark:text-neutral-500 \" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m7 15 5 5 5-5\"/><path d=\"m7 9 5-5 5 5\"/></svg></div>"
}'
class="hidden">
<option selected value="{{ now()->year }}">{{ now()->year }}</option>
</select>
</div>
</div>
{{-- UNIT KERJA --}}
<div>
<label for="unitKerja" class="block mb-2 text-sm font-medium">Unit
Kerja</label>
<input type="text" readonly value="UPT TIK" id="unitKerja"
class="block w-full px-4 py-3 text-sm border-gray-200 rounded-lg focus:border-green focus:ring-green">
</div>
{{-- AKUN BELANJA --}}
<div>
<label for="akunBelanja" class="block mb-2 text-sm font-medium">Akun Belanja</label>
<div wire:ignore class="relative">
<select wire:model='selectedAkunBelanja'
data-hs-select='{
"hasSearch": true,
"searchPlaceholder": "Cari...",
"searchClasses": "block w-full text-sm border-gray-200 rounded-lg focus:border-green focus:ring-green before:absolute before:inset-0 before:z-[1] py-2 px-3",
"searchWrapperClasses": "bg-white p-2 -mx-1 sticky top-0 dark:bg-neutral-900",
"placeholder": "Pilih Akun Belanja...",
"toggleTag": "<button type=\"button\" aria-expanded=\"false\"><span class=\"me-2\" data-icon></span><span class=\"text-gray-800 dark:text-neutral-200 \" data-title></span></button>",
"toggleClasses": "hs-select-disabled:pointer-events-none hs-select-disabled:opacity-50 relative py-3 ps-4 pe-9 flex gap-x-2 text-nowrap w-full cursor-pointer bg-white border border-gray-200 rounded-lg text-start text-sm focus:outline-none focus:ring-2 focus:ring-green",
"dropdownClasses": "mt-2 max-h-72 pb-1 px-1 space-y-0.5 z-20 w-full bg-white border border-gray-200 rounded-lg overflow-hidden overflow-y-auto [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-track]:bg-gray-100 [&::-webkit-scrollbar-thumb]:bg-gray-300 dark:[&::-webkit-scrollbar-track]:bg-neutral-700 dark:[&::-webkit-scrollbar-thumb]:bg-neutral-500 dark:bg-neutral-900 dark:border-neutral-700",
"optionClasses": "py-2 px-4 w-full text-sm text-gray-800 cursor-pointer hover:bg-gray-50 rounded-lg focus:outline-none focus:bg-gray-100",
"optionTemplate": "<div class=\"flex justify-between items-center w-full\"><span data-title></span><span class=\"hidden hs-selected:block\"><svg class=\"shrink-0 size-3.5 text-blue-600\" xmlns=\"http:.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg></span></div>",
"extraMarkup": "<div class=\"absolute top-1/2 end-3 -translate-y-1/2\"><svg class=\"shrink-0 size-3.5 text-gray-500 dark:text-neutral-500 \" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m7 15 5 5 5-5\"/><path d=\"m7 9 5-5 5 5\"/></svg></div>"
}'
class="hidden" id="akunBelanja">
<option value="">Pilih</option>
@foreach($akunBelanja as $akun)
<option value="{{ $akun['id'] }}">{{ $akun['name'] }}</option>
@endforeach
</select>
@error('selectedAkunBelanja')
<div class="absolute inset-y-0 flex items-center pointer-events-none end-0 pe-8">
<x-ri-error-warning-line class="text-red-500 shrink-0 size-4" />
</div>
@enderror
</div>
@error('selectedAkunBelanja')
<p class="mt-1 text-sm text-red-600" id="error-selectedAkunBelanja">{{ $message }}</p>
@enderror
</div>
{{-- NOMOR FAKTUR --}}
<div>
<label for="nomorFaktur" class="block mb-2 text-sm font-medium ">Nomor Faktur
</label>
<div class="relative">
<input wire:model='nomorFaktur' type="text" id="nomorFaktur"
class="block w-full px-4 py-3 text-sm border-gray-200 @error('nomorFaktur') border-red-500 focus:border-red-500 focus:ring-red-50 @enderror rounded-lg focus:border-green focus:ring-green">
@error('nomorFaktur')
<div class="absolute inset-y-0 flex items-center pointer-events-none end-0 pe-3">
<x-ri-error-warning-line class="text-red-500 shrink-0 size-4" />
</div>
@enderror
</div>
@error('nomorFaktur')
<p class="mt-1 text-sm text-red-600" id="error-nomorFaktur">{{ $message }}</p>
@enderror
</div>
{{-- TANGGAL FAKTUR --}}
<div x-data="{}" x-init="flatpickr($refs.tanggalFaktur, {
dateFormat: 'd F Y',
locale: 'id',
});">
<label for="tanggalFaktur" class="block mb-2 text-sm font-medium ">Tanggal Faktur</label>
<div class="relative">
<div>
<input wire:model='tanggalFaktur' x-ref="tanggalFaktur" type="text" id="tanggalFaktur"
placeholder="Pilih Tanggal..."
class="block w-full px-4 cursor-pointer py-3 text-sm border-gray-200 @error('tanggalFaktur') border-red-500 focus:border-red-500 focus:ring-red-50 @enderror rounded-lg focus:border-green focus:ring-green"
x-bind:readonly='true'>
</div>
@error('tanggalFaktur')
<div class="absolute inset-y-0 flex items-center pointer-events-none end-0 pe-3">
<x-ri-error-warning-line class="text-red-500 shrink-0 size-4" />
</div>
@enderror
</div>
@error('tanggalFaktur')
<p class="mt-1 text-sm text-red-600" id="error-tanggalFaktur">{{ $message }}</p>
@enderror
</div>
</div>
</x-slot:body>
</x-modal>
@script
<script>
$wire.on('closeModal', () => {
HSOverlay.close('#modal-tambah-faktur-barang')
HSSelect.getInstance('#akunBelanja').setValue('')
})
</script>
@endscript
Thankyou