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 18 votes! Yum!
// ... use statements hidden - click to show
#[AsLiveComponent]
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()
{
$this->isEditing = true;
}
#[LiveAction]
public function save(EntityManagerInterface $entityManager)
{
// 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 %}
<div class="alert alert-success">{{ flashMessage }}</div>
{% endif %}
<div class="d-inline-flex">
{% if isEditing %}
{# The form isn't used, but allows the user to hit enter to save. #}
<form class="row g-3">
<div class="input-group mb-3 col">
{% set error = this.getError('food.name') %}
<div class="form-floating">
<input
type="text"
data-model="food.name"
class="form-control form-control-lg{{ error ? ' is-invalid' }}"
autofocus
id="food_name"
/>
<label for="food_name">Food name</label>
</div>
<button
data-action="live#action:prevent"
data-live-action-param="save"
class="btn btn-outline btn-outline-{{ error ? 'danger' : 'secondary' }}"
>Save</button>
{% if error %}
<div class="invalid-feedback">{{ error.message }}</div>
{% endif %}
</div>
<div class="form-text">Clear the field to trigger validation!</div>
</form>
{% else %}
<h2>{{ food.name }}</h2>
<button
data-action="live#action"
data-live-action-param="activateEditing"
class="btn btn-link"
title="Click to edit!"
>
<twig:ux:icon name="pencil" />
</button>
{% endif %}
</div>
<hr>
<p>
The <strong>{{ food.name }}</strong> has {{ food.votes }} votes! Yum!
</p>
</div>
Author
weaverryan
Published
2023-02-21