Search code examples
javascriptlaravel-livewiresweetalert2

When in liwevire data listing when sweetalert2 alert is opened I lose rows count


In laravel 10 / filamentphp 3 app I added sweetalert2 support and show some alert error messages using this library, but when I got 404 error on delete and show sweetalert2 error message - my list of data has 0 length, so I got message like "No data found". In my component :

namespace App\Livewire\Admin;

...
use App\Models\StaffUser;
use Livewire\Component;
/*
http://127.0.0.1:8000/admin/staff-users
*/
class CrudStaffUsers extends Component
{
    // Listing component rows
    protected $staffUserDataRows = [];
    ...
    public function mount(string $defaultAction = '')
    {
        $this->retrieveDbData(1);
    }

    public function render()
    {
        return view('livewire.admin.crud-staff-users', [
            'staffUserDataRows' => $this->staffUserDataRows,
            'staffUserRowsCount' => $this->getStaffUserRowsCount()
        ])->layout('components.layouts.admin');
    }


    protected function retrieveDbData($from): void
    {
        $this->staffUserDataRows = StaffUser
            ::getByName($this->filters['name'], $this->filters['extended_search'])
            ->withCount('news')
            ->orderBy('created_at', 'desc')
            ->paginate(10);
    }

    public function updatedPage()
    {
        $this->retrieveDbData(2);
    }


    public function updated($property, $value)
    {
        $this->retrieveDbData(3);
    }


    public function paginationView()
    {
        return 'admin-tailwind';
    }



    protected function getStaffUserRowsCount()
    {
        return StaffUser
            ::getByName($this->filters['name'], $this->filters['extended_search'])
            ->count();
    }

    public function destroy(int $id)
    {
        try {
            $staffUser = StaffUser::getById($id+100)->firstOrFail();  // TRY INVALID ID
        } catch (ModelNotFoundException $e) {
            self::dispatchAlert(DispatchAlertTypeEnum::ERROR,'Deleting staff user: ' . $e->getMessage(), $this->pageTitle);
            return;
        }

        try {
            DB::beginTransaction();
            $staffUser->delete();
            DB::commit();
        } catch (QueryException | \Exception $e) {
            DB::rollBack();
        }
    }
}

Method dispatchAlert calls event in resources/js/app.js:

window.addEventListener('clientAlert', (event) => {

    Swal.fire({
        icon: event.detail[0].type,
        title: event.detail[0].title,
        html: event.detail[0].message,
        showConfirmButton: true,
        timer: 4500
    });
})

and in blade template resources/views/livewire/admin/crud-staff-users.blade.php :

count($staffUserDataRows)::{{ print_r(count($staffUserDataRows), true)}};;<br>
$staffUserRowsCount::{{ print_r($staffUserRowsCount, true)}};;<br>


    @if(count($staffUserDataRows) == 0)
        <div class="m-2 p-2 warning_text">
            {!! AppIconFacade::get(IconEnum::Warning) !!}There are no staff users found !
        </div>
    @endif

    @if(count($staffUserDataRows) > 0)
        <div class="my-0 mx-2 p-0 overflow-x-auto">
            <table class="editor_listing_table mb-4">

So when sweetalert2 alert is opened value count($staffUserDataRows) has 0 value. I suppose that as listibng lost focus I got this issue.

Can it be salved somehow? I would like some client library with with alert message...


Solution

  • When a backend action is called using Livewire to manage an event, the render() method is executed.
    Keep in mind also that on every call to the backend the class is reinstantiated.

    So I suppose you have a Delete button which calls the destroy() method in the backend passing the record id.
    When destroy() finishes, with or without an error, the variable $staffUserDataRows has the value set in the declaration, so it is an empty array.

    A possible solution is to reload the variable content when you delete a row. (Note that from what I can see from your code you could move the call to the retrieveDbData() method on the render() and execute it only there).

    class MyComponent extends Component
    {
        // Listing component rows
        protected $staffUserDataRows = [];
    
       .....
    
       public function destroy(int $id)
       {
           $errorMsg = '';
           $exception = NULL;
    
           try {
              $staffUser = StaffUser::getById($id+100)->firstOrFail();  // TRY INVALID ID
    
              DB::beginTransaction();
              $staffUser->delete();
              DB::commit();
           }
           catch (ModelNotFoundException $e) {
    
              $errorMsg = 'Staff user not found';
              $exception = $e;
           }
           catch (QueryException | \Exception $e) {
              DB::rollBack();
              $errorMsg = 'Deleting staff user';
              $exception = $e;
           }
           finally {
               $this->retrieveDbData();
           }
    
           if ($exception) {
    
             self::dispatchAlert(DispatchAlertTypeEnum::ERROR,$errorMsg, $this->pageTitle);
    
             logger($exception->getMessage()); // this is a simple example 
    
           }
        }
    
       
        .....
        
    
        public function render()
        {
            // $this->retrieveDbData(); By enabling this line you can remove all other *$this->retrieveDbData()* in the class
    
            return view('livewire.sweet-alert03', [
                'staffUserDataRows' => $this->staffUserDataRows,
                'staffUserRowsCount' => $this->getStaffUserRowsCount()
            ])->layout('components.layouts.admin');
        }
    
        .....
    }