Debug School

rakesh kumar
rakesh kumar

Posted on

Explain the use of component in laravel livewire

how component represent state and behavior

Inline components

command to create inline component

Setting properties

How to access Livewire components properties in component's class

How to access Livewire components properties in blade view

How Livewire components properties store data in blade view

Which method is used to pass livewire data component to blade view

How to identify individual items within a list ,array,collection in blade file

How to perform data binding in input field to livewire component properties

How to calling action like save methods

What are the 2 ways to render livewire component on page

How to loading assets

How to execute script

Components are the building blocks of your Livewire application. They combine state and behavior to create reusable pieces of UI for your front end.

example

how component represent state and behavior

The state represents the data or properties of the component, while behavior represents the actions or methods that can be performed on that data. Let's illustrate this with a coding example:

Suppose we want to create a simple counter component that allows users to increment and decrement a counter value.

First, let's define the state and behavior of the component:

// app/Http/Livewire/Counter.php

namespace App\Http\Livewire;

use Livewire\Component;

class Counter extends Component
{
    public $count = 0;

    public function increment()
    {
        $this->count++;
    }

    public function decrement()
    {
        $this->count--;
    }

    public function render()
    {
        return view('livewire.counter');
    }
}
Enter fullscreen mode Exit fullscreen mode

In this component, $count represents the state of the counter. We also define two methods, increment() and decrement(), which represent the behavior of the counter component.

Next, let's create the corresponding view for this component:

<!-- resources/views/livewire/counter.blade.php -->

<div>
    <h1>Counter: {{ $count }}</h1>
    <button wire:click="increment">Increment</button>
    <button wire:click="decrement">Decrement</button>
</div>
Enter fullscreen mode Exit fullscreen mode

In this view, we display the current counter value ($count) and provide buttons to increment and decrement the counter.

Now, you can include this Livewire component in your views or blade files:

<!-- resources/views/welcome.blade.php -->

<!DOCTYPE html>
<html>
<head>
    <title>Counter Component</title>
    @livewireStyles
</head>
<body>

    <livewire:counter />

    @livewireScripts
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

With this setup, the Counter component encapsulates both the state (counter value) and behavior (incrementing and decrementing) of the counter. You can reuse this component in multiple parts of your application, and it will maintain its state and behavior independently. This demonstrates how components in Laravel Livewire combine state and behavior to create reusable pieces of UI.

Inline components

If your component is fairly small, you may want to create an inline component. Inline components are single-file Livewire components whose view template is contained directly in the render() method rather than a separate file:

<?php

namespace App\Livewire;

use Livewire\Component;

class CreatePost extends Component
{
    public function render()
    {
        return <<<'HTML' 
        <div>
            {{-- Your Blade template goes here... --}}
        </div>
        HTML;
    }
}
Enter fullscreen mode Exit fullscreen mode

You can create inline components by adding the --inline flag to the make:livewire command:

command to create inline component

php artisan make:livewire CreatePost --inline
Enter fullscreen mode Exit fullscreen mode

Setting properties

Livewire components have properties that store data and can be easily accessed within the component's class and Blade view. This section discusses the basics of adding a property to a component and using it in your application.

To add a property to a Livewire component, declare a public property in your component class. For example, let's create a $title property in the CreatePost component:

<?php

namespace App\Livewire;

use Livewire\Component;

class CreatePost extends Component
{
    public $title = 'Post title...';

    public function render()
    {
        return view('livewire.create-post');
    }
}
#Accessing properties in the view
Enter fullscreen mode Exit fullscreen mode

Component properties are automatically made available to the component's Blade view. You can reference it using standard Blade syntax. Here we'll display the value of the $title property:

<div>
    <h1>Title: "{{ $title }}"</h1>
</div>
Enter fullscreen mode Exit fullscreen mode

The rendered output of this component would be:

<div>
    <h1>Title: "Post title..."</h1>
</div>
Enter fullscreen mode Exit fullscreen mode

How to access Livewire components properties in component's class

here's a simple example of how you can access Livewire component properties within the component's class in a Laravel application:

Let's say you have a Livewire component called Counter with a property $count:

// app/Http/Livewire/Counter.php

namespace App\Http\Livewire;

use Livewire\Component;

class Counter extends Component
{
    public $count = 0;

    public function render()
    {
        return view('livewire.counter');
    }
}
Enter fullscreen mode Exit fullscreen mode

And here's the corresponding blade view file:

<!-- resources/views/livewire/counter.blade.php -->

<div>
    <h1>{{ $count }}</h1>
    <button wire:click="increment">Increment</button>
</div>
Enter fullscreen mode Exit fullscreen mode

Now, let's say you want to access the $count property within the component's class itself. You can do so by using the $this keyword:

// app/Http/Livewire/Counter.php

namespace App\Http\Livewire;

use Livewire\Component;

class Counter extends Component
{
    public $count = 0;

    public function increment()
    {
        $this->count++;
    }

    public function render()
    {
        // Accessing $count property within the class
        $doubledCount = $this->count * 2;

        return view('livewire.counter', [
            'doubledCount' => $doubledCount,
        ]);
    }
}
Enter fullscreen mode Exit fullscreen mode

In the above example, within the render() method, we accessed the $count property using $this->count and then performed some operation on it (doubling its value) before passing it to the view.

You can now use $doubledCount in your blade view as follows:

<!-- resources/views/livewire/counter.blade.php -->

<div>
    <h1>{{ $count }}</h1>
    <h2>Doubled Count: {{ $doubledCount }}</h2>
    <button wire:click="increment">Increment</button>
</div>
Enter fullscreen mode Exit fullscreen mode

This demonstrates how you can access Livewire component properties within the component's class itself.

Another Examples

here's a basic example of a CRUD (Create, Read, Update, Delete) Livewire component in Laravel, where we'll access Livewire component properties within the component's class:

Let's create a Livewire component called ProductComponent:

php artisan make:livewire ProductComponent
Enter fullscreen mode Exit fullscreen mode

Now, let's define the component's class:

// app/Http/Livewire/ProductComponent.php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Product;

class ProductComponent extends Component
{
    public $products;
    public $name;
    public $description;

    public function mount()
    {
        $this->products = Product::all();
    }

    public function create()
    {
        $this->validate([
            'name' => 'required',
            'description' => 'required',
        ]);

        Product::create([
            'name' => $this->name,
            'description' => $this->description,
        ]);

        $this->resetFields();
        $this->mount();
    }

    public function delete($productId)
    {
        Product::destroy($productId);
        $this->mount();
    }

    public function render()
    {
        return view('livewire.product-component');
    }

    private function resetFields()
    {
        $this->name = '';
        $this->description = '';
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, let's create the corresponding view for this component:

<!-- resources/views/livewire/product-component.blade.php -->

<div>
    <h1>Products</h1>

    <form wire:submit.prevent="create">
        <input type="text" wire:model="name" placeholder="Name">
        @error('name') <span>{{ $message }}</span> @enderror

        <input type="text" wire:model="description" placeholder="Description">
        @error('description') <span>{{ $message }}</span> @enderror

        <button type="submit">Add Product</button>
    </form>

    <ul>
        @foreach($products as $product)
            <li>
                {{ $product->name }} - {{ $product->description }}
                <button wire:click="delete({{ $product->id }})">Delete</button>
            </li>
        @endforeach
    </ul>
</div>
Enter fullscreen mode Exit fullscreen mode

Image description

Note
In above example $products, $name, and $description component properties to be used mount and create method so we can say Livewire components properties is accessed in component's class

How to access Livewire components properties in blade view

In above example $products, $name, and $description component properties to be used in blade file (product-component.blade.php) so we can say Livewire components properties is accessible in blade view

class Counter extends Component
{
    public $count = 0;
}
Enter fullscreen mode Exit fullscreen mode
 <h1>{{ $count }}</h1>
Enter fullscreen mode Exit fullscreen mode
<!-- resources/views/livewire/counter.blade.php -->

<div>
    <h1>{{ $count }}</h1>
    <h2>Doubled Count: {{ $doubledCount }}</h2>
    <button wire:click="increment">Increment</button>
</div>
Enter fullscreen mode Exit fullscreen mode

How Livewire components properties store data in blade view

In above example $products, $name, and $description component properties to be stored in create method using

Product::create([
            'name' => $this->name,
            'description' => $this->description,
        ]);
Enter fullscreen mode Exit fullscreen mode
public function create()
    {
        $this->validate([
            'name' => 'required',
            'description' => 'required',
        ]);

        Product::create([
            'name' => $this->name,
            'description' => $this->description,
        ]);

        $this->resetFields();
        $this->mount();
    }
Enter fullscreen mode Exit fullscreen mode

Which method is used to pass livewire data component to blade view

render() method

In addition to accessing properties from the view, you can explicitly pass data to the view from the render() method, like you might typically do from a controller. This can be useful when you want to pass additional data without first storing it as a property—because properties have specific performance and security implications.

To pass data to the view in the render() method, you can use the with() method on the view instance. For example, let's say you want to pass the post author's name to the view. In this case, the post's author is the currently authenticated user:

<?php

namespace App\Livewire;

use Illuminate\Support\Facades\Auth;
use Livewire\Component;

class CreatePost extends Component
{
    public $title;

    public function render()
    {
        return view('livewire.create-post')->with([
            'author' => Auth::user()->name,
        ]);
    }
}
Enter fullscreen mode Exit fullscreen mode

Now you may access the $author property from the component's Blade view:

<div>
    <h1>Title: {{ $title }}</h1>

    <span>Author: {{ $author }}</span>
</div>
Enter fullscreen mode Exit fullscreen mode

How to identify individual items within a list ,array,collection in blade file

When looping through data in a Livewire template using @foreach, you must add a unique wire:key attribute to the root element rendered by the loop.

Without a wire:key attribute present within a Blade loop, Livewire won't be able to properly match old elements to their new positions when the loop changes. This can cause many hard to diagnose issues in your application.

For example, if you are looping through an array of posts, you may set the wire:key attribute to the post's ID:

<div>
    @foreach ($posts as $post)
        <div wire:key="{{ $post->id }}"> 
            <!-- ... -->
        </div>
    @endforeach
</div>
Enter fullscreen mode Exit fullscreen mode

If you are looping through an array that is rendering Livewire components you may set the key as a component attribute :key() or pass the key as a third argument when using the @livewire directive.

<div>
    @foreach ($posts as $post)
        <livewire:post-item :$post :key="$post->id">

        @livewire(PostItem::class, ['post' => $post], key($post->id))
    @endforeach
</div>
Enter fullscreen mode Exit fullscreen mode

Another Example

In Laravel Livewire, the wire:key directive is used to manage the state of dynamic lists or collections rendered in the view. It helps Livewire identify individual items within a list and efficiently update the DOM when items are added, removed, or reordered.

Let's illustrate the use of wire:key with an example of rendering a dynamic list of items:

First, let's create a Livewire component to manage a list of tasks:

// app/Http/Livewire/TaskList.php

namespace App\Http\Livewire;

use Livewire\Component;

class TaskList extends Component
{
    public $tasks = [];

   public function addTask($taskName)
    {
        // If the tasks array is empty initially, initialize it with an empty value
        if (empty($this->tasks)) {
            $this->tasks = [];
        }

        $this->tasks[] = ['name' => $taskName, 'completed' => false];
    }

    public function removeTask($index)
    {
        unset($this->tasks[$index]);
        $this->tasks = array_values($this->tasks); // Re-index the array after removing an item
    }

    public function render()
    {
        return view('livewire.task-list');
    }
}
Enter fullscreen mode Exit fullscreen mode

Next, let's create the corresponding view for this component:

<!-- resources/views/livewire/task-list.blade.php -->

<div>
    <h2>Task List</h2>

    <ul>
        @foreach ($tasks as $index => $task)
            <li wire:key="{{ $index }}">
                <input type="checkbox" wire:model="tasks.{{ $index }}.completed"> {{ $task['name'] }}
                <button wire:click="removeTask({{ $index }})">Remove</button>
            </li>
        @endforeach
    </ul>

    <input type="text" wire:model="newTask" placeholder="Enter new task">
    <button wire:click="addTask(newTask)">Add Task</button>
</div>
Enter fullscreen mode Exit fullscreen mode

In this view, we're rendering a list of tasks stored in the $tasks array. Each task item is identified by its index using the wire:key directive. This ensures that Livewire can efficiently track changes to individual items within the list.

The addTask() method adds a new task to the $tasks array, and the removeTask() method removes a task based on its index.

Now, you can include this Livewire component in your views or blade files:

<!-- resources/views/welcome.blade.php -->

<!DOCTYPE html>
<html>
<head>
    <title>Task List Component</title>
    @livewireStyles
</head>
<body>

    <livewire:task-list />

    @livewireScripts
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

With this setup, the TaskList component can dynamically add and remove tasks from the list, and Livewire efficiently updates the DOM using the wire:key directive to identify individual items within the list. This ensures smooth and responsive UI updates for dynamic lists in your application.

How to perform data binding in input field to livewire component properties

One of Livewire's most powerful features is "data binding": the ability to automatically keep properties in-sync with form inputs on the page.

Let's bind the $title property from the CreatePost component to a text input using the wire:model directive:

<form>
    <label for="title">Title:</label>

    <input type="text" id="title" wire:model="title"> 
</form>
Enter fullscreen mode Exit fullscreen mode

Any changes made to the text input will be automatically synchronized with the $title property in your Livewire component.

How to calling action like save methods

Actions are methods within your Livewire component that handle user interactions or perform specific tasks. They're often useful for responding to button clicks or form submissions on a page.

To learn more about actions, let's add a save action to the CreatePost component:

<?php

namespace App\Livewire;

use Livewire\Component;
use App\Models\Post;

class CreatePost extends Component
{
    public $title;

    public function save() 
    {
        $post = Post::create([
            'title' => $this->title
        ]);

        return redirect()->to('/posts')
             ->with('status', 'Post created!');
    }

    public function render()
    {
        return view('livewire.create-post');
    }
}
Enter fullscreen mode Exit fullscreen mode

Next, let's call the save action from the component's Blade view by adding the wire:submit directive to the

element:
<form wire:submit="save"> 
    <label for="title">Title:</label>

    <input type="text" id="title" wire:model="title">

    <button type="submit">Save</button>
</form>

When the "Save" button is clicked, the save() method in your Livewire component will be executed and your component will re-render.

What are the 2 ways to render livewire component on page

There are two ways to render a Livewire component on a page:

  1. Include it within an existing Blade view
  2. Assign it directly to a route as a full-page component Let's cover the first way to render your component, as it's simpler than the second.

You can include a Livewire component in your Blade templates using the
syntax:

<livewire:create-post />

If the component class is nested deeper within the app/Livewire/ directory, you may use the . character to indicate directory nesting. For example, if we assume a component is located at app/Livewire/EditorPosts/CreatePost.php, we may render it like so:

<livewire:editor-posts.create-post />

You must use kebab-case
As you can see in the snippets above, you must use the kebab-cased version of the component name. Using the StudlyCase version of the name () is invalid and won't be recognized by Livewire.

#Passing data into components
To pass outside data into a Livewire component, you can use attributes on the component tag. This is useful when you want to initialize a component with specific data.

To pass an initial value to the $title property of the CreatePost component, you can use the following syntax:

<livewire:create-post title="Initial Title" />

If you need to pass dynamic values or variables to a component, you can write PHP expressions in component attributes by prefixing the attribute with a colon:

<livewire:create-post :title="$initialTitle" />

Data passed into components is received through the mount() lifecycle hook as method parameters. In this case, to assign the $title parameter to a property, you would write a mount() method like the following:

<?php

namespace App\Livewire;

use Livewire\Component;

class CreatePost extends Component
{
    public $title;

    public function mount($title = null)
    {
        $this->title = $title;
    }

    // ...
}

In this example, the $title property will be initialized with the value "Initial Title".

You can think of the mount() method as a class constructor. It runs on the initial load of the component, but not on subsequent requests within a page. You can learn more about mount() and other helpful lifecycle hooks within the lifecycle documentation.

To reduce boilerplate code in your components, you can alternatively omit the mount() method and Livewire will automatically set any properties on your component with names matching the passed in values:


<?php

namespace App\Livewire;

use Livewire\Component;

class CreatePost extends Component
{
    public $title; 

    // ...
}

This is effectively the same as assigning $title inside a mount() method.

Full-page components

Livewire allows you to assign components directly to a route in your Laravel application. These are called "full-page components". You can use them to build standalone pages with logic and views, fully encapsulated within a Livewire component.

To create a full-page component, define a route in your routes/web.php file and use the Route::get() method to map the component directly to a specific URL. For example, let's imagine you want to render the CreatePost component at the dedicated route: /posts/create.

You can accomplish this by adding the following line to your routes/web.php file:

use App\Livewire\CreatePost;

Route::get('/posts/create', CreatePost::class);

Now, when you visit the /posts/create path in your browser, the CreatePost component will be rendered as a full-page component.

laravel component

Top comments (0)