Appearance
Debug Livewire
- Sometimes you need to debug your Livewire components to see what's going on under the hood.
- There are a few ways to "look" in real-time at what's going on with your Livewire component.
- here are a few ways to debug your Livewire components.
Livewire DevTools
- Livewire DevTools is a Chrome extension that allows you to inspect your Livewire components in real-time.
- At the time of writing (September 23), Livewire DevTools only works with Livewire v2 and not with Livewire v3. 😦
- Hopefully, this will be fixed soon...
Wiretap
- Wiretap is a new development tool for Livewire.
- It was showcased by Caleb Porzio (the founder of Livewire) at Laracon US 2023 in Nashville.
- However, at the time of writing (October 23), it has not been officially released
Livewire log component
- We can also create our own Blade component that will show us all the properties of a Livewire component on the page and/or in the browser console.
Preparation
- Create a new livewire-log component inside the components folder:
resources/views/components/tmk/livewire-log.blade.php
- Paste the following code inside the component:
livewire-log.blade.php code
php
@php
/* config --------------------- */
$onlyDebugMode = true; // only show this component in debug mode
$sidebar = true; // shows the result in a sidebar on the page
$console = true; // show the result in the developer console
$consoleJson = true; // show the result in the console in json format (true) or as an object (false)
/* end config ----------------- */
// only show this component in debug mode
if(!config('app.debug') && $onlyDebugMode) return;
$output = [];
$prefixes = ['__', 'app', 'errors', 'attributes', 'slot', 'output', 'prefixes', 'show', 'onlyDebugMode', 'sidebar', 'console', 'consoleJson'];
$vars = get_defined_vars();
foreach($vars as $key => $value) {
if (!array_reduce($prefixes, function($carry, $item) use ($key) {
return $carry || str_starts_with($key, $item);
}, false)) {
if ($key === '_instance') {
json_encode($value) !== '{}' && json_encode($value) !== '[]' ? $output['public properties'] = $value : '';
} else {
$output[$key] = $value;
}
}
}
@endphp
<div>
{{-- sidebar --}}
@if($sidebar)
<div x-date class="
absolute p-4 top-0 left-0 z-50 bg-slate-500/50 text-white backdrop-blur-sm shadow-2xl border border-slate-500
transition -translate-x-full
hover:translate-x-0 duration-300 ease-in-out">
<x-si-livewire
class="w-6 h-6 absolute top-4 -right-8 text-pink-400 drop-shadow-[0_1.2px_1.2px_rgba(0,0,0,0.6)]"/>
<div class="overflow-auto">
<h1 class="font-bold mb-2">Livewire properties</h1>
@foreach(array_reverse($output) as $key => $value)
<div x-data="{show: false}" x-cloak>
<hr class="my-2 border-slate-500">
<button @click="show = !show" class="w-full flex items-center cursor-pointer gap-2">
<span class="text-xl transition-all block"
:class="show ? 'rotate-45' : ''">+</span>
<p class="text-sm italic cursor-pointer">{{ $key }}</p>
</button>
<pre class="text-sm" x-show="show"
x-transition>{{ json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) }}</pre>
</div>
@endforeach
</div>
</div>
@endif
{{-- devtools console --}}
@if($console)
@foreach(array_reverse($output) as $key => $value)
@if($consoleJson)
<script>
console.log('%c {!! $key !!}: ', 'background: #222; color: #fff');
console.log(JSON.stringify({!! json_encode($value) !!}, null, 2));
</script>
@else
<script>
console.log('%c {!! $key !!}: ', 'background: #222; color: #fff');
console.log({!! json_encode($value) !!});
</script>
@endif
@endforeach
@endif
</div>
@php
/* config --------------------- */
$onlyDebugMode = true; // only show this component in debug mode
$sidebar = true; // shows the result in a sidebar on the page
$console = true; // show the result in the developer console
$consoleJson = true; // show the result in the console in json format (true) or as an object (false)
/* end config ----------------- */
// only show this component in debug mode
if(!config('app.debug') && $onlyDebugMode) return;
$output = [];
$prefixes = ['__', 'app', 'errors', 'attributes', 'slot', 'output', 'prefixes', 'show', 'onlyDebugMode', 'sidebar', 'console', 'consoleJson'];
$vars = get_defined_vars();
foreach($vars as $key => $value) {
if (!array_reduce($prefixes, function($carry, $item) use ($key) {
return $carry || str_starts_with($key, $item);
}, false)) {
if ($key === '_instance') {
json_encode($value) !== '{}' && json_encode($value) !== '[]' ? $output['public properties'] = $value : '';
} else {
$output[$key] = $value;
}
}
}
@endphp
<div>
{{-- sidebar --}}
@if($sidebar)
<div x-date class="
absolute p-4 top-0 left-0 z-50 bg-slate-500/50 text-white backdrop-blur-sm shadow-2xl border border-slate-500
transition -translate-x-full
hover:translate-x-0 duration-300 ease-in-out">
<x-si-livewire
class="w-6 h-6 absolute top-4 -right-8 text-pink-400 drop-shadow-[0_1.2px_1.2px_rgba(0,0,0,0.6)]"/>
<div class="overflow-auto">
<h1 class="font-bold mb-2">Livewire properties</h1>
@foreach(array_reverse($output) as $key => $value)
<div x-data="{show: false}" x-cloak>
<hr class="my-2 border-slate-500">
<button @click="show = !show" class="w-full flex items-center cursor-pointer gap-2">
<span class="text-xl transition-all block"
:class="show ? 'rotate-45' : ''">+</span>
<p class="text-sm italic cursor-pointer">{{ $key }}</p>
</button>
<pre class="text-sm" x-show="show"
x-transition>{{ json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) }}</pre>
</div>
@endforeach
</div>
</div>
@endif
{{-- devtools console --}}
@if($console)
@foreach(array_reverse($output) as $key => $value)
@if($consoleJson)
<script>
console.log('%c {!! $key !!}: ', 'background: #222; color: #fff');
console.log(JSON.stringify({!! json_encode($value) !!}, null, 2));
</script>
@else
<script>
console.log('%c {!! $key !!}: ', 'background: #222; color: #fff');
console.log({!! json_encode($value) !!});
</script>
@endif
@endforeach
@endif
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Usage
- Let's take the following Livewire component as an example (you don't have to make this component yourself, it's just an example)
- The LiveWire component has:
- three public properties:
$perPage
,$showModal
and$person
- one variable:
$users
in therender()
method
- three public properties:
php
class Log extends Component
{
public int $perPage = 10;
public bool $showModal = false;
public array $person = [
'name' => 'John Doe',
'email' => 'john.doe@example.com',
];
#[Layout('layouts.vinylshop', ['title' => 'Livewire log example',])]
public function render()
{
$users = User::orderBy('name')->get();
return view('livewire.log', compact('users'));
}
}
class Log extends Component
{
public int $perPage = 10;
public bool $showModal = false;
public array $person = [
'name' => 'John Doe',
'email' => 'john.doe@example.com',
];
#[Layout('layouts.vinylshop', ['title' => 'Livewire log example',])]
public function render()
{
$users = User::orderBy('name')->get();
return view('livewire.log', compact('users'));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- If you have a lot of properties and variables, it can be difficult to remember them all when you're working on the view.
- That's where the
livewire-log
component comes in handy. - All you have to do is include the component in your view.
- All the public properties of the Livewire component will be shown:
- by hovering over the Livewire icon in the top left corner of the page
- inside the browser console tab (F12)
php
<div>
<x-tmk.list type="group">
@foreach($users as $user)
<li class="p-2">
<span class="font-bold">{{ $user->name }}</span>
<span class="block italic">{{ $user->email }}</span>
</li>
@endforeach
</x-tmk.list>
<x-tmk.livewire-log />
</div>
<div>
<x-tmk.list type="group">
@foreach($users as $user)
<li class="p-2">
<span class="font-bold">{{ $user->name }}</span>
<span class="block italic">{{ $user->email }}</span>
</li>
@endforeach
</x-tmk.list>
<x-tmk.livewire-log />
</div>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- The variables in the
render()
method are not shown yet. - All you have to do is add them as dynamic properties (starting with a semicolon) to the
livewire-log
component
E.g.:users="$users"
where$users
is the variable in therender()
method and:users
is the name that will be shown in the log.
php
<div>
<x-tmk.list type="group">
@foreach($users as $user)
<li class="p-2">
<span class="font-bold">{{ $user->name }}</span>
<span class="block italic">{{ $user->email }}</span>
</li>
@endforeach
</x-tmk.list>
<x-tmk.livewire-log :users="$users" />
</div>
<div>
<x-tmk.list type="group">
@foreach($users as $user)
<li class="p-2">
<span class="font-bold">{{ $user->name }}</span>
<span class="block italic">{{ $user->email }}</span>
</li>
@endforeach
</x-tmk.list>
<x-tmk.livewire-log :users="$users" />
</div>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- If you are, for example, only interested in the first user, the just change the name of the dynamic property to
:firstUser="$users->first()"
or:firstUser="$users[1]"
php
<div>
<x-tmk.list type="group">
@foreach($users as $user)
<li class="p-2">
<span class="font-bold">{{ $user->name }}</span>
<span class="block italic">{{ $user->email }}</span>
</li>
@endforeach
</x-tmk.list>
<x-tmk.livewire-log :firstUser="$users[1]" />
</div>
<div>
<x-tmk.list type="group">
@foreach($users as $user)
<li class="p-2">
<span class="font-bold">{{ $user->name }}</span>
<span class="block italic">{{ $user->email }}</span>
</li>
@endforeach
</x-tmk.list>
<x-tmk.livewire-log :firstUser="$users[1]" />
</div>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Important notice about interactive pages
- If you have an interactive page, like, for example, a search field, you have to keep in mind that:
- the content in the sidebar will change immediately with the new content.
- the content in the browser console will not change as it always shows the content of the page when it was loaded.
Configuration
The component has a few configuration options:
- Line 2:
$onlyDebugMode
: if set totrue
, the component will only be included on the page when the app is in debug mode (APP_DEBUG=true
in the.env
file) - Line 3:
$sidebar
: if set totrue
, the result will be shown on a sidebar on the page - Line 4:
$console
: if set totrue
, the result will be shown in the browser console tab - Line 5:
$consoleJson
the result will be shown in the browser console tab:- in json format (if set to
true
) - as an object (if set to
false
)
- in json format (if set to