In this section, let's dive into more complex and practical stuff: we will create a CRUD with Livewire. Let's start by creating a table in Laravel, moving it to Livewire, and adding pagination to the table.
Initial Structure
For the initial Laravel project, we will have a Product
Model and a page to list all the products.
database/migrations/xxxx_create_products_table.php:
Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('name'); $table->text('description'); $table->timestamps();});
app/Models/Product.php:
use Illuminate\Database\Eloquent\Factories\HasFactory; class Product extends Model{ use HasFactory; protected $fillable = [ 'name', 'description', ];}
database/factories/ProductFactory.php:
class ProductFactory extends Factory{ public function definition(): array { return [ 'name' => $this->faker->name(), 'description' => $this->faker->text(50), ]; }}
database/seeders/DatabaseSeeder.php:
class DatabaseSeeder extends Seeder{ public function run(): void { Product::factory(50)->create(); }}
Don't forget to run Seeder when migrating database
php artisan migrate --seed
.
app/Http/Controllers/ProductController.php:
use App\Models\Product;use Illuminate\Contracts\View\View; class ProductController extends Controller{ public function index(): View { $products = Product::all(); return view('products.index', compact('products')); }}
routes/web.php:
Route::get('products', [\App\Http\Controllers\ProductController::class, 'index']);
resources/views/products/index.blade.php:
<x-app-layout> // ... layout header code <div class="min-w-full align-middle"> <table class="min-w-full divide-y divide-gray-200 border"> <thead> <tr> <th class="px-6 py-3 bg-gray-50 text-left"> <span class="text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">Name</span> </th> <th class="px-6 py-3 bg-gray-50 text-left"> <span class="text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">Description</span> </th> <th class="px-6 py-3 bg-gray-50 text-left"> </th> </tr> </thead> <tbody class="bg-white divide-y divide-gray-200 divide-solid"> @forelse($products as $product) <tr class="bg-white"> <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900"> {{ $product->name }} </td> <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-900"> {{ $product->description }} </td> <td> <a href="#" class="inline-flex items-center px-4 py-2 bg-gray-800 rounded-md font-semibold text-xs text-white uppercase tracking-widest"> Edit </a> <a href="#" class="inline-flex items-center px-4 py-2 bg-red-600 rounded-md font-semibold text-xs text-white uppercase tracking-widest"> Delete </a> </td> </tr> @empty <tr> <td class="px-6 py-4 text-sm" colspan="3"> No products were found. </td> </tr> @endforelse </tbody> </table></div> // ... layout footer code </x-app-layout>
Notice: In this tutorial, we use the Laravel Breeze layout with x-app-layout
Blade component, but feel free to use any other layout. Read more in the docs.
After visiting the /products
page, you should see a table with the list of products.
Move to Livewire Component
Now let's move the table to the Livewire component. First, we need a component.
php artisan make:livewire Products
Next, the whole table code move into the Livewire components...