Why search is run when text input lose focus?

Hello,
In laravel 7 with livewire 1.3 I make listing of data with filter text
input(it has wire:model.lazy defined) and “Search” button and I need to run search when
“Search” button is clicked.
But search is run when text input lose focus without clicking on “Search” button.
I have a component app/Http/Livewire/Admin/Facilities.php:

<?php

namespace App\Http\Livewire\Admin;

use App\library\CheckValueType;
use App\Settings;
use DB;
use Illuminate\Validation\Rule;
use Livewire\Component;
use App\Facility;
use Livewire\WithPagination;


class Facilities extends Component
{
    use WithPagination;

    public $form= [
        'name'=>'',
        'descr'=> '',
        'created_at'=> ''
    ];

    public $current_facility_id;
    public $filter_name;
    public $updateMode = 'browse';

    public function render()
    {
        \Log::info( '-1 Facilities $this->filter_name ::' . print_r(  $this->filter_name, true  ) );
        // when text input lose focus I see tracing code above is added to log

        $facility_rows_count = Facility
            ::getByName($this->filter_name, true)
            ->count();
        $backend_per_page = Settings::getValue('backend_per_page', CheckValueType::cvtInteger, 20);

        $this->emit('facility_opened', [ 'mode'=>'browse', 'id'=>null ] );
        return view('livewire.admin.facilities.container', [
            'facilityDataRows' => Facility
                ::orderBy('created_at', 'desc')
                ->getByName($this->filter_name, true)
                ->paginate($backend_per_page),
            'facility_rows_count'=> $facility_rows_count
        ]);
    }

and in resources/views/livewire/admin/facilities/container.blade.php :

<div>
    
    @inject('viewFuncs', 'App\library\viewFuncs')
    
    <div class="page_content">
        
        @include('livewire.common.alert_messages')
        
        <div class="card form-admin-facilities">
            
            <div class="card-body card-block">
                
                @if($updateMode=='browse')
                    <h3 class="card-header">
                        {{ $facility_rows_count }}
                        {{ Str::plural('Facility', $facility_rows_count) }}
                    </h3>
                    
                    <div class="content_with_right_button">
                        <div class="content_with_right_button_left_content">
                            <h4 class="card-subtitle ml-3 mr-3">
                                Your can create/edit/delete facilities
                            </h4>
                        </div>
                        <div class="content_with_right_button_right_button m-0 m-0">
                            <button type="button" wire:click="add()" class="btn btn-xs btn-success action_link">Add</button>
                        </div>
                    </div>
                    
                    <fieldset class="bordered text-muted p-2 m-2">
                        <legend class="bordered">Filters</legend>
                        <div class="content_with_right_button">
                            <div class="content_with_right_button_left_content">
                                <input class="form-control admin_control_input" type="text" wire:model.lazy="filter_name">
                            </div>
                            <div class="content_with_right_button_right_button pl-2">
                                <button class="btn btn-outline-secondary nowrap_block" wire:click="render" type="button">
                                    Search
                                </button>
                            </div>
                        </div>
                    </fieldset>
                @endif {{-- @if($updateMode=='browse')--}}
                
                @if($updateMode=='browse')
                    
                    @if(count($facilityDataRows) > 0)
                        <div class="table-responsive table-wrapper-for-data-listing">
                            <table class="table table-striped table-data-listing">
                                <thead>
                                <tr>
                                    <th>Id</th>
                                    <th>Name</th>
                                    <th>Description</th>
                                    <th>Created</th>
                                    <th></th>
                                </tr>
                                </thead>
                                
                                @foreach($facilityDataRows as $nextFacilityDataRow)
                                    <tr>
                                        <td class="text-right m-0">
                                            <a wire:click="edit({{$nextFacilityDataRow->id}})"
                                               class="p-1 a_edit_item_{{$nextFacilityDataRow->id}} a_link">
                                                {{$nextFacilityDataRow->id}}
                                            </a>
                                        </td>
                                        <td class="text-left m-0">
                                            {{$nextFacilityDataRow->name}}
                                        </td>
                                        <td class="text-left m-0">{{$nextFacilityDataRow->descr}}</td>
                                        <td class="text-left m-0">{{$viewFuncs->getFormattedDate($nextFacilityDataRow->created_at)}}</td>
                                        <td class="nowrap_block m-1">
                                            <a wire:click="edit({{$nextFacilityDataRow->id}})"
                                               class="p-1 a_edit_item_{{$nextFacilityDataRow->id}} a_link">
                                            </a>
                                            <a onclick="return confirm('Are you sure you want to remove the facility?') || event.stopImmediatePropagation()"
                                               wire:click="destroy({{$nextFacilityDataRow->id}})" type="button" class="p-1
                                                a_delete_item_{{$nextFacilityDataRow->id}} a_link">
                                            </a>
                                        </td>
                                    </tr>
                                @endforeach
                            
                            </table>
                        </div> <!-- <div class="table-responsive table-wrapper-for-data-listing"> -->
                    
                    @endif {{-- @if(count($facilityDataRows) > 0) --}}
                @endif {{-- @if($updateMode=='browse')  --}}
            </div> <!-- <div class="card-body card-block"> -->
            
            <section class="card-footer">
                @if($updateMode=='browse')
                    {{ $facilityDataRows->links() }}
                @endif {{-- @if($updateMode=='browse')  --}}
            </section>
        
        </div> <!-- <div class="card form-admin-facilities"> -->
    
    </div>
</div>

<script>
    window.livewire.on('facility_opened', data => {
        console.log('facility_opened data::')
        console.log(data)
        alertsInit(data.mode,data.id)
    })
</script>

My “Search” button has type=“button” and no submit rule for form(I do not have any form) or button.
Why it works in wrong way and how to fix it ?
Thanks!

It’s working the right way as you have changed a public property so Livewire will run the render() method. Since your render() method has the filter_name public property, you will get the new data already filtered.

You will need to use an additional property e.g name that gets set inside a search() method in your component and use the name property to filter your data in the render() method.

1 Like

you might want to use alphineJS instead, something like

<div wire:model="search" x-data="{ search: ''}">
    <input x-model="search" />
    <button x-on:click="$dispatch('input', search)"></button>
</div>

Thanks! Does render() method is triggered when any public var is changed? Reading docs I missed it… Please give a link to it.

alphineJS - is out of my expirense. Has it some advantages working with livewire ?

there is a lot, if you read the docs there are powerful stuffs it can do with livewire

1 Like

Internally, Livewire will listen for an input event on the element, and when triggered, it will send an AJAX request to re-render the component with the new data.

1 Like

I suppose this https://laravel-livewire.com/docs/alpine-js link?

as alphineJS - is out of my expirense please give a link how to start with it ?
Link above seems good if I already have some expirense?

Reading doc at https://laravel-livewire.com/docs/alpine-js
I see support of DatePicker, Color-picker . Any other components(like modal dialogs, sliders etc…?)
I work with bootstrap 4.5/jquery 3.5. Is alphineJS replacement of jquery ?

hey @mstdmstd

if you want to work with AlpineJs it pretty simple and you can learn it within an hour and it’s great with livewire

you can check the alpinejs Repository or if you prefer screencasts you can check this amazing free 1 Hour of alpine

Good Luck.

1 Like