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
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"/>
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;
}
...
}
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>
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'];
}
...
}
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>
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 function 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';
}
}
This is how you would call it in you blade
component:
<div class="news-grid-item">
{{ $saySomething }}
...
</div>
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;
}
}
And in the component:
<div class="news-grid-item">
{{ $saySomething('Hello World') }}
...
</div>
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);
}
}
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>
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);
}
}
And our blade
component can remain nice and clean:
<div class="news-grid-item">
{{ $title }}
...
</div>
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');
}
}
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>
Read more about class-based components in the Laravel official docs:
👉 https://laravel.com/docs/7.x/blade#components
✍ For more posts about Laravel:
https://yossiabramov.com/
Top comments (0)