Tutorial: Learn Laravel Livewire by Building a Todo App
Part 1: Building a Standard Todo App
Hi there 👋🏾. I'm a software engineer that enjoys building stuff and talking about them. I also tinker a bit with hardware and robotics using Arduino and ROS.
Introduction
Laravel is a battle-tested PHP Framework for building websites and web apps. It was built by Taylor Otwell in 2011. Laravel has been used to build all sorts of software. From Ecommerce websites to Fintech apps. In this post, we will learn a few concepts about Laravel by building a standard TodoApp. In the next post, we will dig deeper into Laravel and add authentication, Mail, Schedules and Jobs to our application. This 2-part series will teach you core backend concepts such as
Authentication
Working with Email
Cron jobs
Deployment
Knowledge of Laravel
What is Livewire
Livewire is a library that enables developers to build apps that update the DOM without page refresh. It's like building Single Page Apps without building an API.
INSERT LIVEWIRE GIF
Installing Jetstream and Livewire
Run this command to install Livewire
composer require laravel/jetstream
Afterwards, install Livewire using
php artisan jetstream:install livewire
Finally, publish the required packages using
php artisan vendor:publish --tag=jetstream-views
Main content
Todos Component
Create the Todos component by running
php artisan make:livewire todos
This creates a view and a controller
Creating the Todo Model
When building with Livewire, you still work the core functions of Laravel such as artisan commands. Create a todo model along with its migration using:
php artisan make:model todo -m
Now, add this block to the up method of the migration file
$table->string('todo_text');
$table->boolean('is_done')->default(false);
Finally, migrate the database.
php artisan migrate
Now, add the Todo model to the Todos Livewire controller.
use App\Models\Todo;
Creating a Todo Item
To add a new todo, we will build a form on the frontend. Let's start with a normal form
<div class="container my-5">
<form class="form-inline">
<div class="form-group">
<label for="todo-text">Something to do</label>
<input class="form-control mx-4" id="todo-text" autofocus type="text" required />
<button class="btn btn-primary" type="submit">Add</button>
</div>
</form>
This form simply refreshes the page when submitted. It isn't hooked to any controller, so it does nothing. We will structure our logic such that whenever a user types in text, some public string variable on our Todos class will be updated with the text. Then, when the form is submitted, we use the public string variable to create a new todo on the database.
Livewire helps us write this logic using models. A model is a two-way channel that allows us to set and display data in an HTML input element. The data in the variable can change via a method in the controller or a user's input from the frontend.
Creating a todo_text model
Create a public variable on the Todos controller
public $todo_text;
Then add a wire:model attribute to the input element
<input class="form-control mx-4" id="todo-text" autofocus type="text" required wire:model="todo_text" />
To see the model in action, add $todo_text in twig below the form and then, type on the input element.
{{ $todo_text }}
INSERT TYPING GIF
Amazing right? Go ahead and remove the {{ $todo_text }} from the template.
Handling Form Submit
Livewire has a lot of similarities with VueJS, like models and event modifiers such as preventdefault. Add a wire:submit attribute to the form
wire:submit.prevent="addTodo"
and also create a public method called addTodo on the Todos component.
public function addTodo()
{
Todo::create(["todo_text" => $this->todo_text, "is_done" => false]);
$this->todo_text = "";
}
See how we set the value of $todo_text back to an empty string? This will also update the input element on the app. You can as many crazy todo items as your heart desires. I won't judge.
Rendering data
The Todos component class has a render which points the app to the blade view. The render method also helps us pass data down to the component. Replace the content of the render method with this block
$todos = Todo::all();
return view('livewire.todos', ["todos" => $todos]);
Displaying Data on the Frontend
To display data on the frontend, you only need to loop through the $todos array. Add this forloop below the form.
@foreach($todos as $todo)
<div class=" d-flex align-items-baseline my-2">
<input {{ $todo->is_done ? "checked": "" }} type="checkbox" />
<p class="mx-4 {{$todo->is_done ? "strikethrough": ""}}">{{$todo->todo_text}}</p>
<div class="d-flex justify-content-between align-items-center">
<button>
<img src="/icons/edit-icon.svg" alt="edit todo" class="mr-2" style="width:15px; cursor: pointer">
</button>
<button type="button" class="close text-danger" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
@endforeach
Add the following block below the loop to display a default text if a user has completed his daily tasks.
@if(!count($todos))
<p>Nothing to do</p>
@endif
You should see something like this on the browser.
INSERT IMAGE OF DISPLAYED TODOS
Setting a Todo as Done
To
Handling Todo Updates
Deleting Todo Items
Adding filters
Mini Wrap Up
In this tutorial, we learned
What Livewire offers
How Livewire works within a Laravel project
How to perform basic CRUD operations using Livewire
In the next tutorial, we will look into Authentication, Mail and Cron Jobs. If you found this tutorial useful, you can support me by following me on Twitter and subscribing to my Hashnode Newsletter. Thanks for dropping by. Adios ✌🏾🧡.
