Livewire: Custom error page done right
Published: 2023-10-19 12:42:11

When something goes wrong with Livewire you see a modal. As a developer you know you have to click outside to close it. **Users don't!**


In this example I have used components from  [MaryUI](https://mary-ui.com).


When you click a button that fires a 403 you see this modal.

```php

public function delete()
{
   abort(403, 'You can`t do that ....');
}

```

![403](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x6qia0xgb6dkh0rnhia4.png)


When you navigate to a page does not exist you see this full page.

```
http://localhost:8019/noooooooo
```


![404](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/peo3l3qz695va24rq05m.png)


## 1: Create an empty layout


`File: views/components/layouts/empty.blade`


```html
<html>
<head>
    ...
</head>
<body class="[...] bg-base-200">
   {{ $slot }}
</body>
</html>

```

## 2 : Create a error page


`File: views/errors/error.blade.php`



This will override default Laravel error page. Notice we rely on `$isLivewire` to decide what to do with buttons. 

- If it is a modal show close button.
- If it is not a modal show reload button.


Same page works for a modal or full page errors. 


```html
<x-layouts.empty>
    <div class="flex">
        <div class="mx-auto text-center">
            <img src="/error.png" width="300" class="mx-auto" />

            <div class="text-xl font-bold">Oops!</div>
            <div class="text-lg mx-auto max-w-4xl">{{ $message }}</div>

            <div class="flex mt-10">
                <div class="mx-auto grid md:grid-cols-2 gap-3">

                    <x-button :label="$isLivewire ? 'Close' : 'Reload'"
                              :icon="$isLivewire ? 'o-x-mark' : 'o-arrow-path'"
                              :onclick="$isLivewire
                                        ? 'window.parent.document.getElementById(\'livewire-error\').remove()'
                                        : 'window.location.reload()'"
                              class="btn-primary" />

                    <x-button label="Home"
                              icon="o-home"
                              onclick="window.parent.location.href = '/'"
                              class="btn-outline" />
                </div>
            </div>
        </div>
    </div>
</x-layouts.empty>

```

## 3: Exception Handler `render()`


`File: app/Exceptions/Handler.php`


This overrides Laravel error rendering. See more at [https://laravel.com/docs/10.x/errors](https://laravel.com/docs/10.x/errors)


When `APP_ENV=local` we display default Laravel error page. For any other value like `production` we display our custom error page describe above.



```php
public function render($request, Throwable $e)
{
   // Uses native error page while developing
   if (app()->environment() == 'local') {
      return parent::render($request, $e);
   } 

   // Allow redirect if auth exception
   if ($e instanceof AuthenticationException) {
      return parent::render($request, $e);
   }
        

   $status = parent::render($request, $e)->getStatusCode();
   $isLivewire = $request->hasHeader('X-Livewire');

   // Call error page        
   return response()->view('errors.error', [
         'isLivewire' => $isLivewire,
         'message' => $e->getMessage()
      ], $status);
}

```


## Better!



```php

public function delete()
{
   abort(403, 'You can`t do that ....');
}

```

![403](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lgodxccxlvojqsj4q3wr.png)


```
http://localhost:8019/noooooooo
```

![404](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7q3iwr7ye6b46xnjko8k.png)



### Can we do it better? Yes!

You probably want to have a default message error based on status here instead to use raw error message.

[...]
403 - Go away!
404 - I can't find this page.
500 - Something is wrong our side.
[...]

```php
[
   ...
   'message' => $e->getMessage()
]
```



Thank you!