Inline Editing
Inline editing? Simple. Use LiveComponents to track if you're in "edit" mode, let
the user update any fields on your entity, and save through a LiveAction.
Banana 🍌
The Banana 🍌 has 27 votes! Yum!
// ... use statements hidden - click to show
#[AsLiveComponent]
final class InlineEditFood extends AbstractController
{
use DefaultActionTrait;
use ValidatableComponentTrait;
/** This allows us to have a data-model="food.name" */
#[LiveProp(writable: ['name'])]
/** When we validate, we want to also validate the Food object */
#[Assert\Valid]
public Food $food;
/** Tracks whether the component is in "edit" mode or not */
#[LiveProp]
public bool $isEditing = false;
/**
* A temporary message to show to the user.
*
* This is purposely not a LiveProp: this is a "temporary" value that
* will only show one time.
*/
public ?string $flashMessage = null;
#[LiveAction]
public function activateEditing(): void
{
$this->isEditing = true;
}
#[LiveAction]
public function save(EntityManagerInterface $entityManager): void
{
// if validation fails, this throws an exception & the component re-renders
$this->validate();
$this->isEditing = false;
$this->flashMessage = 'Saved! Well, not actually because this is a demo (if you refresh, the value will go back).';
// in a real app, we would save!
// $entityManager->flush();
}
}
<div {{ attributes }}>
{% if flashMessage %}
<twig:Alert variant="success" class="mb-4">{{ flashMessage }}</twig:Alert>
{% endif %}
<div class="inline-flex">
{% if isEditing %}
{# The form isn't used, but allows the user to hit enter to save. #}
<form class="flex flex-col gap-4">
<div class="mb-4">
{% set error = this.getError('food.name') %}
<twig:Form:Label for="food_name">Food name</twig:Form:Label>
<div class="flex gap-2">
<twig:Form:Input type="text" id="food_name" data-model="food.name" hasError="{{ error is not null }}" class="py-2" autofocus />
<twig:Button
variant="outline"
class="shrink-0 {{ error ? 'border-signal-red text-signal-red' }}"
data-action="live#action:prevent"
data-live-action-param="save"
>Save</twig:Button>
</div>
<twig:Form:Errors errors="{{ error ? error.message : null }}" />
</div>
<div class="text-sm text-muted">Clear the field to trigger validation!</div>
</form>
{% else %}
<h2>{{ food.name }}</h2>
<twig:Button
variant="link"
data-action="live#action"
data-live-action-param="activateEditing"
title="Click to edit!"
>
<twig:ux:icon name="pencil" />
</twig:Button>
{% endif %}
</div>
<hr>
<p>
The <strong>{{ food.name }}</strong> has {{ food.votes }} votes! Yum!
</p>
</div>
Author
weaverryan
Published
2023-02-21