In my previous post about Laravel 7 Class Based Components I went over creating class based components as well as passing data to components and displaying them. In this post I will go over component class methods. And once again, class based components allow us to create robust components and harness the power of classes, so do more exploring on your own – you will not regrate it! ☝
Component Class Methods
Let’s say we have a news site with a news grid container and some news items in it. We would probably create 2 components: a news grid container component and a news grid item component. Let’s create our components:
php artisan make:component NewsGridContainer php artisan make:component NewsGridItem
content_copyTerminal
Then, we could pass a news items array with news items to our news grid container, inside the grid container.
In our welcome.blade.php
:
@php $newsItems = [ [ 'id' => 1, 'title' => 'this is my title', 'body' => '......', 'featured_image' => '/images/featured.jpeg', ], ]; @endphp <x-news-grid-container :news-items="$newsItems"/>
content_copywelcome.blade.php
In order to pass our $newsItems
array to news-grid-container.blade.php
we first need to declare it as public property in the app/Views/Components/NewsGridContainer.php
class and assign it in the __construct()
method:
<?php namespace App\View\Components; use Illuminate\View\Component; class NewsGridContainer extends Component { public $newsItems; /** * Create a new component instance. * * @return void */ public function __construct($newsItems) { $this->newsItems = $newsItems; } ... }
content_copyPHP
And in resources/views/components/news-grid-container.blade.php
:
<div class="grid-container"> @foreach ($newsItems as $item) <x-news-grid-item :news-item="$item" /> @endforeach </div>
content_copynews-grid-container.blade.php
Here are our news grid item class properties declarations and __construct()
:
<?php namespace App\View\Components; use Illuminate\View\Component; class NewsGridItem extends Component { public $title; public $body; public $featured_image; /** * Create a new component instance. * * @return void */ public function __construct($newsItem) { $this->title = $newsItem['title']; $this->body = $newsItem['body']; $this->featured_image = $newsItem['featured_image']; } ... }
content_copyPHP
And our resources/views/components/news-grid-item.blade.php
:
<div class="news-grid-item"> <img class="featured-image" src="{{ $featured_image }}" alt="featured image"> <div class="content-body"> <h3 class="title">{{ $title }}</h3> <p class="excerpt">{{ $body }}</p> <button class="read-more">READ MORE</button> </div> </div>
content_copynews-grid-item.blade.php
Now that we have some components to work with, let’s go over some basic ways of using component class methods.
First, let’s create a simple public method saySomething()
that will simply return ‘Hello World’.
<?php namespace App\View\Components; use Illuminate\View\Component; class NewsGridItem extends Component { ... public function saySomething(){ return 'Hello World'; } }
content_copyPHP
This is how you would call it in your blade
component:
<div class="news-grid-item"> {{ $saySomething }} ... </div>
content_copyPHP
If we want to pass some data to this function, we first need to change it a bit:
<?php namespace App\View\Components; use Illuminate\View\Component; class NewsGridItem extends Component { ... public function saySomething($msg){ return $msg; } }
content_copyPHP
And in the component:
<div class="news-grid-item"> {{ $saySomething('Hello World') }} ... </div>
content_copyPHP
Now, let’s say our news item’s title is all in lower case letters and we want to “Title Case” it. We have a lot of ways of doing it: Modify the title already in our __construct
method, or maybe inside our blade
component itself. we can also create a public function called titleCase($title)
in our class and pass the title to it:
<?php namespace App\View\Components; use Illuminate\Support\Str; use Illuminate\View\Component; class NewsGridItem extends Component { ... public function titleCase($title){ return Str::title($title); } }
content_copyPHP
Then, we would need to call it like this in our blade component (or do something even uglier in our __construct
method):
<div class="news-grid-item"> {{ $titleCase($title) }} ... </div>
content_copyPHP
However, there is a much nicer way of modifying properties. We can create a public function that shares the name of a declared property like this:
<?php namespace App\View\Components; use Illuminate\Support\Str; use Illuminate\View\Component; class NewsGridItem extends Component { ... public function title(){ return Str::title($this->title); } }
content_copyPHP
And our blade
component can remain nice and clean:
<div class="news-grid-item"> {{ $title }} ... </div>
content_copyPHP
I’ve added 2 more methods to this class just to show a bit more of what is possible – but this does not even scratch the surface. Here is the full result:
<?php namespace App\View\Components; use Illuminate\Support\Str; use Illuminate\View\Component; class NewsGridItem extends Component { public $title; public $body; public $featured_image; /** * Create a new component instance. * * @return void */ public function __construct($newsItem) { $this->title = $newsItem['title']; $this->body = $newsItem['body']; $this->featured_image = $newsItem['featured_image']; } /** * Get the view / contents that represent the component. * * @return \Illuminate\View\View|string */ public function render() { return view('components.news-grid-item'); } public function title() { return Str::title($this->title); } public function body() { return Str::limit($this->body, 40); } public function image(){ // Check if image exists in public assets folder if(file_exists(public_path($this->featured_image))){ return asset($this->featured_image); } // Fallback return asset('/images/fallback.png'); } }
content_copyPHP
And our blade
component:
<div class="news-grid-item"> <img class="featured-image" src="{{ $image }}" alt="featured image"> <div class="content-body"> <h3 class="title">{{ $title }}</h3> <p class="excerpt">{{ $body }}</p> <button class="read-more">READ MORE</button> </div> </div>
content_copyPHP
Read more about class-based components in the Laravel official docs:
👉 https://laravel.com/docs/7.x/blade#components