Rendering Components

 
Visual Learner?
Start with our free screencasts.
Watch Now

Livewire Directive (@livewire)

The most basic way to render a Livewire component on a page is using the @livewire blade directive:

<div>
    @livewire('search-posts')
</div>

If you are on Laravel 7 or greater, you can use the tag syntax.

<livewire:search-posts />

Passing Initial Parameters

You can pass data into a component by passing additional parameters into the @livewire directive. For example, let's say we have a ShowContact Livewire component that needs to know which contact to show. Here's how you would pass in a contact model.

@livewire('show-contact', ['contact' => $contact])

If you are on Laravel 7 or greater, you can use the tag syntax.

<livewire:show-contact :contact="$contact">

Now, you can intercept those parameters and store the data as public properties using the mount() method/lifecycle hook.

In Livewire components, you use the mount() instead of a class constructor (__construct()) like you may be used to.
use Livewire\Component;

class ShowContact extends Component
{
    public $name;
    public $email;

    public function mount($contact)
    {
        $this->name = $contact->name;
        $this->email = $contact->email;
    }

    ...
}

Dependency Injection

Like a controller, you can inject dependencies by adding type-hinted parameters before passed-in ones.

use Livewire\Component;
use \Illuminate\Session\SessionManager

class ShowContact extends Component
{
    public $name;
    public $email;

    public function mount(SessionManager $session, $contact)
    {
        $session->put("contact.{$contact->id}.last_viewed", now());

        $this->name = $contact->name;
        $this->email = $contact->email;
    }

    ...
}

Accessing The Request

Because mount() runs during the initial page load, it is the only place in a Livewire component you can reliably access Laravel's request object.

For example, you can set the initial value of a property based on a request parameter (possibly something passed in the query-string).

use Livewire\Component;
use \Illuminate\Session\SessionManager

class ShowContact extends Component
{
    public $name;
    public $email;

    public function mount($contact, $sectionHeading = '')
    {
        $this->name = $contact->name;
        $this->email = $contact->email;
        $this->sectionHeading = request('section_heading', $sectionHeading);
    }

    ...
}

Livewire Route Registration

If you find yourself writing controllers and views that only return a Livewire component, you might want to use Livewire's routing helper to cut out the extra boilerplate code. Take a look at the following example:

Before

// Route
Route::get('/home', '[email protected]');

// Controller
class HomeController extends Controller
{
    public function show()
    {
        return view('home');
    }
}

// View
@extends('layouts.app')

@section('content')
    @livewire('counter')
@endsection

After

// Route
Route::livewire('/home', 'counter');

Note: for this feature to work, Livewire assumes you have a layout stored in resources/views/layouts/app.blade.php that yields a "content" section (@yield('content'))

Custom Layout

If you use a different layout file or section name, you can configure these in the standard way you configure laravel routes:

// Customizing layout
Route::livewire('/home', 'counter')
    ->layout('layouts.base');

// Customizing section (@yield('body'))
Route::livewire('/home', 'counter')
    ->section('body');

// Passing parameters to the layout (Like native @extends('layouts.app', ['title' => 'foo']))
Route::livewire('/home', 'counter')
    ->layout('layouts.app', [
        'title' => 'foo'
    ]);

You can also configure these settings for an entire route group using the group option array syntax:

Route::group(['layout' => 'layouts.base', 'section' => 'body'], function () {
    //
});

Or the fluent alternative:

Route::layout('layouts.base')->section('body')->group(function () {
    //
});

Route Parameters

Often you need to access route parameters inside your controller methods. Because we are no longer using controllers, Livewire attempts to mimick this behavior through it's mount lifecycle hook. For example:

web.php

Route::livewire('/contact/{id}', 'show-contact');

App\Http\Livewire\ShowContact.php

use Livewire\Component;

class ShowContact extends Component
{
    public $name;
    public $email;

    public function mount($id)
    {
        $contact = User::find($id);

        $this->name = $contact->name;
        $this->email = $contact->email;
    }

    ...
}

As you can see, the mount method in a Livewire component is acting like a controller method would as far as it's parameters go. If you visit /contact/123, the $id variable passed into the mount method will contain the value 123.

Route Model Binding

Like you would expect, Livewire components implement all functionality you're used to in your controllers including route model binding. For example:

web.php

Route::livewire('/contact/{user}', 'show-contact');

App\Http\Livewire\ShowContact.php

use Livewire\Component;

class ShowContact extends Component
{
    public $contact;

    public function mount(User $user)
    {
        $this->contact = $user;
    }
}

Now, after visiting /contact/123, the value passed into mount will be an instance of the User model with id 123.

The Render Method

A Livewire component's render method gets called on the initial page load AND every subsequent component update.

In simple components, you don't need to define a `render` method yourself. The base Livewire component class has a dynamic `render` method included.

Returning Blade Views

The render() method is expected to return a Blade view, therefore, you can compare it to writing a controller method. Here is an example:

Make sure your Blade view only has ONE root element.
use Livewire\Component;

class ShowPosts extends Component
{
    public function render()
    {
        return view('livewire.show-posts', [
            'posts' => Post::all(),
        ]);
    }
}
<div>
    @foreach ($posts as $post)
        @include('includes.post', $post)
    @endforeach
</div>

Returning Template Strings

If your Livewire project uses Laravel 7 or above, you can optionally return a Blade template string from ->render().

use Livewire\Component;

class DeletePost extends Component
{
    public $post;

    public function mount(Post $post)
    {
        $this->post = $post;
    }

    public function delete()
    {
        $this->post->delete();
    }

    public function render()
    {
        return <<<'blade'
            <div>
                <button wire:click="delete">Delete Post</button>
            </div>
        blade;
    }
}
For inline components like above, you should use the --inline flag during creation: artisan make:livewire delete-post --inline
← Previous Topic

Making Components

Next Topic →

Properties