Table of Contents
📖 3 minutes read
Building Inline Edit UI with Vue.js in Laravel Blade
Inline editing is a great UX pattern – users can edit data right where they see it, without navigating to a separate form. Here’s how to implement it cleanly with Vue.js in a Laravel Blade template.
The Pattern
The key is tracking three states: viewing, editing, and saving. Here’s the basic structure:
new Vue({
el: '#product-details',
data: {
editing: false,
saving: false,
form: {
name: '{{ $product->name }}',
price: '{{ $product->price }}',
description: '{{ $product->description }}'
},
original: {}
},
methods: {
startEditing() {
// Store original values for cancel
this.original = { ...this.form };
this.editing = true;
},
cancelEditing() {
// Restore original values
this.form = { ...this.original };
this.editing = false;
},
async save() {
this.saving = true;
try {
const response = await axios.put(
'/api/products/{{ $product->id }}',
this.form
);
// Update local state with server response
// This keeps UI in sync without page reload
this.form = response.data.product;
this.editing = false;
} catch (error) {
alert('Save failed: ' + error.response.data.message);
} finally {
this.saving = false;
}
}
}
});
The Blade Template
<div id="product-details">
<!-- View mode -->
<div v-if="!editing">
<strong>Name:</strong> @{{ form.name }}<br>
<strong>Price:</strong> $@{{ form.price }}<br>
<strong>Description:</strong> @{{ form.description }}
<button @click="startEditing">Edit</button>
</div>
<!-- Edit mode -->
<div v-else>
<input v-model="form.name" placeholder="Name"><br>
<input v-model="form.price" type="number" placeholder="Price"><br>
<textarea v-model="form.description" placeholder="Description"></textarea>
<button @click="save" :disabled="saving">
@{{ saving ? 'Saving...' : 'Save' }}
</button>
<button @click="cancelEditing" :disabled="saving">Cancel</button>
</div>
</div>
Key Points
- Preserve Original Values: When entering edit mode, clone the form data so cancel can restore it
- Update After Save: After successful save, update
this.formwith the server response. This keeps the UI in sync without refreshing the page - Disable During Save: Disable buttons while
savingis true to prevent duplicate submissions - Handle Empty States: Show appropriate messaging when fields are empty (both in view and edit mode)
The Controller
public function update(Request $request, Product $product)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'price' => 'required|numeric|min:0',
'description' => 'nullable|string'
]);
$product->update($validated);
// Return the updated model
return response()->json([
'product' => $product->fresh()
]);
}
Why This Works
This pattern gives you:
- Instant feedback (no page reload)
- Clean cancel behavior (reverts to original values)
- Server validation (with error handling)
- Optimistic UI updates (form shows saved data immediately)
The secret sauce is updating this.form with the server response after save. This ensures your Vue state matches what’s actually in the database, without needing to reload the entire page.
Leave a Reply