In general, there are two main ways to use Livewire:
- You build the full project with Laravel Controllers, and use Livewire only for small dynamic elements on the pages
- You use Livewire Components instead of Laravel Controllers, with so-called Full-Page Components
The choice is yours, it's a personal preference. In this lesson, let's see how to do it with full-page components.
Routes
Instead of mapping to the Controller in the Routes files, you just need to map directly to the Livewire component.
use App\Livewire\CreatePost; Route::get('/posts/create', CreatePost::class);
Layout Files
Livewire uses Blade component as an application layout. So it needs to have a {{ $slot }}
placeholder. By default, Livewire uses the resources/views/components/layouts/app.blade.php
Blade file for the main layout.
<!DOCTYPE html><html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{ $title ?? 'Page Title' }}</title> </head> <body> {{ $slot }} </body></html>
The main layout's location can be changed in two ways: global and per-component.
Global Layout Configuration
To use the same layout for all components, you can set layout
in the config/livewire.php
to the path where your layout is.
config/livewire.php:
// ... 'layout' => 'layouts.app', // ...
Per-component Layout Configuration
To set the layout for a particular component, you must use the #[Layout]
attribute either above the render
method or the class declaration.
use Livewire\Attributes\Layout;use Livewire\Component; #[Layout('layouts.app')] class CreatePost extends Component{ // ... #[Layout('layouts.app')] public function render() { return view('livewire.create-post'); }}
Or you can have a base Livewire component to set the layout. For example, the layout could be different for the admin. Then, in one Livewire component, you would set the layout.
#[Layout('components.layouts.admin)]class AdminComponent extends \Livewire\Component {}
And all other Livewire components should then extend this AdminComponent
instead of a \Livewire\Component
.
class AdminPanel extends AdminComponent {}
Setting Page Title
Setting a unique title for the page is very useful. First, you need to have a $title
variable in the layouts title section.
<head> <title>{{ $title ?? 'Page Title' }}</title></head>
Next, similar to how you can set the layout per-component using attributes, you can set the title by adding the #[Title]
attribute.
use Livewire\Attributes\Title;use Livewire\Component; class CreatePost extends Component{ // ... #[Title('Create Post')] public function render() { return view('livewire.create-post'); }}
If you need a dynamic title, use the title
method in the component's render
method.
class CreatePost extends Component{ // ... public function render() { return view('livewire.create-post') ->title('Create Post'); }}
And that's it: you don't need Laravel Controllers then, all your Routes may lead to full-page Livewire components.
If we are using resources/views/components/layouts/app.blade.php as global layout
then the config/livewire.php should read
Yes, but you don't necessarily have to have this config, as it is the DEFAULT value.
Quote from the docs: "By default, Livewire will automatically look for a layout file named: resources/views/components/layouts/app.blade.php"
I’m sorry but in my version Laravel/framework 10.35.0 and laravel/breeze 1.26.2 with livewire/livewire 3.3.0 Out of the box Laravel puts the layouts in its one directory. Resources/views/layouts/app.blade.php
Not in resources/views/components/layouts/app.blade.php.
However if you create a new layout using the php artisan make:component AppLayout command it will put the file in the components directory but not in a layouts subdirectory in less you tell it to.
PS. under the latest “Laravel new” you can get Breeze to setup using livewire 3 and the old problems with Alpin.js has been taken care of.
I have the same issue! My app layout is in 'resources/views/layouts/app.blade.php' - What was your workaround for this, Richard? Did you just update the livewire config file to use layouts.app.blade?
Please read the docs about layouts https://livewire.laravel.com/docs/components#layout-files
What is the differnce between mapping directly to the Livewire component like the above example and doing this?
Route::view('/posts/create', 'admin.posts.create');
And then in the 'admin.posts.create' render the posts component?
'<x-app-layout>'<livewire:create-post /></x-app-layout>
The only thing that I can see is that we avoid having an extra file that only renders the component
Using directly component it's called a full page component. Not everyone likes them and not always it's needed. Livewire can be used just in some parts of the page, for example only for comments on the page, or for like/dislike button. But it's more a personal preference.
Got it! And in case that I want to use the index method for the post, is it possible to do it with livewire if we are using it already? I want to avoid having a PostController only for the index method
You can fully use full page Livewire components. In the routes instead of calling controller call the Livewire component. In your case you can name it for example
PostsIndex
.