DEMOS / Live Component

Embedded CollectionType Form

Unlock the potential of Symfony's CollectionType while writing zero JavaScript. This demo shows off adding and removing items entirely in PHP & Twig.

Item Priority
// ... use statements hidden - click to show
use App\Entity\TodoList;
use App\Form\TodoListFormType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\DefaultActionTrait;
use Symfony\UX\LiveComponent\LiveCollectionTrait;

#[AsLiveComponent]
final class TodoListForm extends AbstractController
{
    use DefaultActionTrait;
    use LiveCollectionTrait;

    #[LiveProp(fieldName: 'formData')]
    public ?TodoList $todoList;

    /**
     * @return FormInterface<TodoList>
     */
    protected function instantiateForm(): FormInterface
    {
        return $this->createForm(
            TodoListFormType::class,
            $this->todoList
        );
    }
}
<div
    {{ attributes }}
>
    {{ form_start(form) }}
        <div class="grid grid-cols-12 gap-x-6">
            <div class="col-span-4">
                {{ form_row(form.name, {
                    label: false,
                    attr: {
                        placeholder: 'Give your list a name',
                    },
                }) }}
            </div>
        </div>

        <table class="w-full text-left [&_td]:pr-3 [&_td]:py-1 [&_:is(input,select)]:mb-0">
            <thead>
                <tr>
                    <td>Item</td>
                    <td>Priority</td>
                </tr>
            </thead>
            <tbody>
                {% for item_form in form.todoItems %}
                    <tr>
                        <td>
                            {{ form_row(item_form.description, {
                                label: false,
                                row_attr: {class: ''},
                                attr: {
                                    placeholder: 'Walk the pygmy hippo',
                                },
                            }) }}
                        </td>
                        <td>
                            {{ form_row(item_form.priority, {
                                row_attr: {class: ''},
                                label: false,
                            }) }}
                        </td>
                        <td>
                            {{ form_row(item_form.vars.button_delete, {label: 'X', attr: {class: 'border-signal-red bg-transparent text-signal-red hover:bg-signal-red hover:text-white'}}) }}
                        </td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>

        {{ form_widget(form.todoItems.vars.button_add, {label: '+ Add Item', attr: {class: 'border-body-text bg-transparent text-body-text opacity-75 hover:opacity-100 hover:bg-body-text hover:text-body'}}) }}

        <twig:Button variant="success" type="submit" class="mt-4" formnovalidate>Save</twig:Button>
    {{ form_end(form) }}
</div>
Author weaverryan
Published 2022-06-17