September 1st, 2021

Create a toggle switch with Livewire

Create a toggle switch with Livewire

In this tutorial, we will create an iOS looking like toggle switch button that saves its state in our database using Livewire and Tailwind for styling. We will make our Livewire component reusable so we don’t have to create another component when we want to use the button somewhere else in the application. I’ll show you how to pass ‘data’ dynamically and hydrate your Livewire component ‘on the fly’.

1php artisan livewire:make ToggleButton

Now we have two files. The ToggleButton.php in app/Http/livewire/ and toggle-button.blade.php in resources/views/livewire.

Let’s get the toggle button styled with tailwind from TailwindComponents:

3/* @apply rules for documentation, these do not work as inline style */
4.toggle-checkbox:checked {
5 @apply: right-0 border-green-400;
6 right: 0;
7 border-color: #68D391;
9.toggle-checkbox:checked + .toggle-label {
10 @apply: bg-green-400;
11 background-color: #68D391;
15<div class="
16 relative inline-block w-10 mr-2 align-middle select-none transition
17 duration-200 ease-in
18 ">
19 <input
20 type="checkbox"
21 name="toggle"
22 id="toggle"
23 class="
24 toggle-checkbox absolute block w-6 h-6 rounded-full bg-white
25 border-4 appearance-none cursor-pointer
26 "/>
27 <label for="toggle"
28 class="
29 toggle-label block overflow-hidden h-6 rounded-full
30 bg-gray-300 cursor-pointer
31 ">
32 </label>

Now in our markup, we will want to bind the “hasStock” (you can use isActive or anything related to your project). So the input tag will look like this:

2 wire:model="hasStock"
3 type="checkbox"
4 name="toggle"
5 id="toggle"
6 class="
7 toggle-checkbox absolute block w-6 h-6 rounded-full bg-white
8 border-4 appearance-none cursor-pointer
9 "/>

Now let’s go and create the logic we need in order to make this work (you should have a “stock” field in your database for your model):

3 namespace App\Http\Livewire;
5 use Illuminate\Database\Eloquent\Model;
6 use Livewire\Component;
8 class ToggleButton extends Component
9 {
10 public Model $model;
11 public string $field;
12 public bool $hasStock;
14 public function mount()
15 {
16 $this->hasStock = (bool) $this->model->getAttribute($this->field);
17 }
18 public function render()
19 {
20 return view('livewire.toggle-button');
21 }
22 public function updating($field, $value)
23 {
24 $this->model->setAttribute($this->field, $value)->save();
25 }

In our Livewire component, we don’t want to hardcode the model name and we want to make this component reusable within the project. Therefore, we declared public Model $model which will expect to return an instance of Illuminate\Database\Eloquent\Model. In our case, we will pass the instance as a property of the component in our view.

The component is pretty simple, we have a $model and a $field that matches our database ($product->stock) and we will get these values from our blade view when rendering the component.

Let’s say we render this component on a typical laravel blade view (products.blade.php). So here’s an example of this view:

1@foreach($products as $product)
2 <div>
3 <livewire:toggle-button
4 :model="$product"
5 field="stock"
6 key="{{ $product->id }}" />
7 </div>
8 @endforeach

Since in this view we already have access to the Products::class we can pass and hydrate the $model->field by binding :model to an instance of the model and field as a corresponding field of that model. As you noticed already, we also passed a key to our toggle button. Livewire has no way of keeping track of which button is which and to avoid any unexpected behaviour we set the key to equal the $product->id which is unique.

That’s it. You should now have a fully functional switch button that saves the boolean value of the switch in the database.

Statamic Ninja


Marian Pop

PHP / Laravel Developer. Writing and maintaining @LaravelMagazine. Host of "The Laravel Magazine Podcast". Pronouns: vi/vim.

Subscribe to our newsletter

Get latest news, tutorials, community articles and podcast episodes delivered to your inbox.

Weekly articles
We send a new issue of the newsletter every week on Friday.
No spam
We'll never share your email address and you can opt out at any time.