Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

StarShines's avatar

Filter in Laravel Livewire Payment Component

Hello,

I have 3 models, Invoice , Student and Payment.

Invoice model is related to student model with many to many relationship and there is a pivot table, with invoice_id and student_id. The relationship name on invoice model is studentName.

In payment component view, I have a form as below:

<form wire:submit.prevent="filterInvoices" class="pt-3">
                <div class="form-group">
                    <label class="form-label required" for="student_name">Name</label>

                    <x-select-list class="form-control" required
                        id="student_name" name="student_name"
                        :options="$this->listsForFields['student_name']"
                        wire:model="selectedStudent" />

                    <div class="validation-message">
                        {{ $errors->first('student_name') }}
                    </div>
                </div>

                <div class="form-group">
                    <button class="btn btn-indigo mr-2" type="submit">
                        Filter
                    </button>
                <div>

                    <div>
                        @foreach ($invoices as $invoice)
                            <p>{{ $invoice->invoice_number }}</p>
                        @endforeach
                    </div>
            </form>

In payment component class, I have this:

public array $invoice_no = [];
    public $invoices = [];
    public array $listsForFields = [];

    //for filter card
    public $selectedStudent;
    
public function filterInvoices()
    {
        $this->render();
    }

    public function render()
    {
        // Fetch all the students
        $students = Student::all();

        // Fetch invoices based on the selected student name
        $invoices = Invoice::when($this->selectedStudent, function ($query) {
            $query->whereHas('studentName', function ($q) {
                $q->where('student_id', $this->selectedStudent);
            });
        })->get();

        return view('livewire.payment.create', [
            'students' => $students,
            'invoices' => $invoices,
        ]);

    }


When I click the submit button on the form, nothing happens, no filter is applied. Where my code is wrong.

Many thanks

0 likes
12 replies
Snapey's avatar

why do you have a pivot table? I can understand a student might have many invoices, but why would an invoice have many students?

StarShines's avatar

@Snapey An invoice can have multiple products.

Likewise I have students who are siblings. Because one invoice will be sent to their parents for payment so in other words one family gets one invoice a month with their children names 8n the invoice.

Snapey's avatar

Assuming you have tested your relationships

First step, dd($this->selectedStudent) in your filterInvoices() function

This will show if the form is posting and if the student_id is being passed.

Also, no need to call $this->render() in the filter function as render is always called anyway.

StarShines's avatar

@snapey Same page is being reloaded, nothing is happening. DD is not showing any invoices.

However, the url does change

payment/create?student_name=2 or create?student_name=3

newbie360's avatar

@shunmas

The entry point is here

<x-select-list class="form-control" required
    id="student_name" name="student_name"
    :options="$this->listsForFields['student_name']"
    wire:model="selectedStudent" />

i reformated the code more easy to read

<x-select-list 
    id="student_name" 
    wire:model="selectedStudent"
    name="student_name"
    :options="$this->listsForFields['student_name']"
    class="form-control" 
    required
/>

and i search selectedStudent it finally related to this

$q->where('student_id', $this->selectedStudent);

the $this->selectedStudent value is based on

:options="$this->listsForFields['student_name']"

so the question is what actually rendered code of this component <x-select-list

Snapey's avatar

@shunmas the fact that the URL changes and the page reloads indicates that the submit.prevent is not working. You sure, you have the livewire script loaded?

StarShines's avatar

@newbie360 Here:

<div>
    <div wire:ignore class="w-full">
        @if(isset($attributes['multiple']))
            <div id="{{ $attributes['id'] }}-btn-container" class="mb-3">
                <button type="button" class="btn btn-info btn-sm select-all-button">{{ trans('global.select_all') }}</button>
                <button type="button" class="btn btn-info btn-sm deselect-all-button">{{ trans('global.deselect_all') }}</button>
            </div>
        @endif
        <select class="select2 form-control" data-placeholder="{{ __('Select your option') }}" {{ $attributes }}>
            @if(!isset($attributes['multiple']))
                <option></option>
            @endif
            @foreach($options as $key => $value)
                <option value="{{ $key }}">{{ $value }}</option>
            @endforeach
        </select>
    </div>
</div>
newbie360's avatar

@shunmas No, i mean the select element rendered code,

in your browser inspect the select element

right click on the highlighted code > copy > outter html

paste here

StarShines's avatar

@newbie360 Here:

<div class="form-group">
    <label class="form-label required" for="student_name">Name</label>

    <div>
        <div wire:ignore="" class="w-full">
            <select class="select2 form-control select2-hidden-accessible" data-placeholder="Select your option"
                required="required" id="student_name" name="id" wire:model="selectedStudent" tabindex="-1"
                aria-hidden="true" data-select2-id="student_name">
                <option data-select2-id="18"></option>
                <option value="1">William Smith</option>
                <option value="2">Noah Smith</option>
                <option value="3">Ariyana Smith</option>
            </select><span class="select2 select2-container select2-container--default" dir="ltr"
                data-select2-id="17" style="width: 548px;"><span class="selection"><span
                        class="select2-selection select2-selection--single" role="combobox" aria-haspopup="true"
                        aria-expanded="false" tabindex="0" aria-disabled="false"
                        aria-labelledby="select2-student_name-container"><span class="select2-selection__rendered"
                            id="select2-student_name-container" role="textbox" aria-readonly="true"><span
                                class="select2-selection__placeholder">Select your option</span></span><span
                            class="select2-selection__arrow" role="presentation"><b
                                role="presentation"></b></span></span></span><span class="dropdown-wrapper"
                    aria-hidden="true"></span></span>
        </div>
    </div>


    <button class="btn btn-indigo mr-2" type="submit">
        Filter
    </button>

    <div>

    </div>
</div>
newbie360's avatar

@shunmas your blade component not match the rendered code ......, the name="id"

<x-select-list class="form-control" required
    id="student_name" name="student_name"
    :options="$this->listsForFields['student_name']"
    wire:model="selectedStudent" />
    
required="required" id="student_name" name="id" wire:model="selectedStudent" 

if you aren't posting any data, make sure the filter no problem first

try this, commented out the code below

// public function filterInvoices()
// {
//     $this->render();
// }
{{-- <form wire:submit.prevent="filterInvoices" class="pt-3"> --}}

{{-- </form> --}}

and change

 <div wire:ignore class="w-full">

to

<div class="w-full">

and add dd()

        $invoices = Invoice::when($this->selectedStudent, function ($query) {
            $query->whereHas('studentName', function ($q) {
                $q->where('student_id', $this->selectedStudent);
            });
        })->get();
        
        dd($invoices);
StarShines's avatar

@snapey Its basically Payment Component view file, where I want to do Invoice filtering by student name, so effectively I am using Invoice component in Payment component.

Does it have to have to do with mount method. In my mount, I have this:

  public function mount(Payment $payment)
    {
        $this->payment                      = $payment;
        $this->payment->invoice_amount_paid = '0.00';
        $this->payment->invoice_balance     = '0.00';
        $this->payment->payment_method      = 'Cash';
        $this->payment->created_by          = 'Auth';
        $this->initListsForFields();
```	

Yes, there is no issue with payment component view. Its loading fine.

Please or to participate in this conversation.