Skip to content

Inline Editing

This recipe demonstrates the click-to-edit pattern where users can edit content directly in place without navigating to a separate form.

What We're Building

An editable task list with:

  • Click to edit mode
  • Save/cancel actions
  • Optimistic updates

Complete Implementation

Blade Template

Create resources/views/tasks/list.blade.php:

blade
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Editable Tasks</title>
    @hyper
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-50">
    <div class="max-w-2xl mx-auto px-4 py-12 space-y-4">
        @foreach ($tasks as $task)
        <div 
            @signals([
                "_showEdit_{$task->id}" => false,
                "title_{$task->id}" => $task->title
            ]) 
            class="flex items-center justify-between shadow-lg p-2 rounded-md">
            
            <div class="flex items-center gap-2 flex-grow">
                <!-- Displayed title -->
                <p 
                    data-show="!$_showEdit_{{ $task->id }}" 
                    data-text="$title_{{ $task->id }}"
                    class="px-2 flex-grow">
                </p>

                <!-- Editable input -->
                <input 
                    data-show="$_showEdit_{{ $task->id }}"
                    data-bind="title_{{ $task->id }}"
                    type="text" 
                    class="border border-gray-300 rounded-sm p-1 flex-grow"
                />
            </div>

            <div class="flex items-center gap-2">
                <!-- Edit -->
                <button 
                    data-on:click="$_showEdit_{{ $task->id }} = true"
                    data-show="!$_showEdit_{{ $task->id }}"
                    class="cursor-pointer text-white bg-blue-500 hover:bg-blue-400 rounded-sm p-1">
                    Edit
                </button>

                <!-- Save + Cancel -->
                <div data-show="$_showEdit_{{ $task->id }}" class="flex gap-1">
                    <button 
                        data-on:click="@putx('/tasks/{{ $task->id }}')"
                        class="cursor-pointer text-white bg-green-500 hover:bg-green-400 rounded-sm p-1">
                        Save
                    </button>
                    <button 
                        data-on:click="$_showEdit_{{ $task->id }} = false; $title_{{ $task->id }} = '{{ addslashes($task->title) }}'"
                        class="cursor-pointer text-white bg-gray-400 hover:bg-gray-300 rounded-sm p-1">
                        Cancel
                    </button>
                </div>
            </div>
        </div>
        @endforeach
    </div>
</body>
</html>

Controller

Create app/Http/Controllers/TaskController.php:

php
<?php

namespace App\Http\Controllers;

use App\Models\Task;

class TaskController extends Controller
{
    public function index()
    {
        $tasks = Task::all();

        return view('tasks.list', [
            'tasks' => $tasks
        ]);
    }
}

Routing

In your web.php

php
use App\Http\Controllers\TaskController;
use App\Models\Task;

Route::get('/tasks', [TaskController::class, 'index']);

Route::put('/tasks/{task}', function (Task $task) {
    $validated = signals()->validate([
        "title_{$task->id}" => 'required|string|max:255',
    ]);

    $task->update(['title' => $validated["title_{$task->id}"]]);

    return hyper()->signals([
        "_showEdit_{$task->id}" => false,
        "title_{$task->id}" => $task->title,
    ]);
});

How It Works

Edit Mode Toggle

Local signals _showEdit control the view/edit state:

blade
@signals="{ _showEdit: false }"

Clicking "Edit" toggles the mode and initializes the temp value:

blade
<button data-on:click="$_showEdit = true">Edit</button>

Cancel Action

Canceling discards the temp value and exits edit mode:

blade
<button data-on:click="$_showEdit = false">
    Cancel
</button>

Key Takeaways

1. Local Signals for Edit State: Using _showEdit (Datastar local signals) keeps edit state client-side without server involvement.