Back to all demos
DEMO

Embedded CollectionType Form

src/Twig/TodoListFormComponent.php

use App\Entity\TodoList;
use App\Form\TodoListForm;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveAction;
use Symfony\UX\LiveComponent\Attribute\LiveArg;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\ComponentWithFormTrait;
use Symfony\UX\LiveComponent\DefaultActionTrait;

#[AsLiveComponent('todo_list_form')]
class TodoListFormComponent extends AbstractController
{
    use ComponentWithFormTrait;
    use DefaultActionTrait;

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

    protected function instantiateForm(): FormInterface
    {
        return $this->createForm(
            TodoListForm::class,
            $this->todoList
        );
    }

    #[LiveAction]
    public function addItem(): void
    {
        $this->formValues['todoItems'][] = [];
    }

    #[LiveAction]
    public function removeItem(#[LiveArg] int $index): void
    {
        unset($this->formValues['todoItems'][$index]);
    }
}

templates/components/todo_list_form.html.twig

<div
    {{ attributes }}
>
    {{ form_start(form) }}
        <div class="row">
            <div class="col-4">
                {{ form_row(form.name, {
                    label: false,
                    attr: {
                        placeholder: 'Give your list a name'
                    }
                }) }}
            </div>
        </div>

        <table class="table table-borderless form-no-mb">
            <thead>
                <tr>
                    <td>Item</td>
                    <td>Priority</td>
                </tr>
            </thead>
            <tbody>
                {% for key, itemForm in form.todoItems %}
                    <tr>
                        <td>
                            {{ form_row(itemForm.description, {
                                label: false,
                                attr: {
                                    placeholder: 'Walk the pygmy hippo'
                                }
                            }) }}
                        </td>

                        <td>
                            {{ form_row(itemForm.priority, {
                                row_attr: {class: ''},
                                label: false,
                            }) }}
                        </td>
                        <td>
                            <button data-action="live#action" data-action-name="removeItem(index={{ key }})" type="button" class="btn btn-outline-danger">X</button>
                        </td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>

        {% do form.todoItems.setRendered %}
        <button data-action="live#action" data-action-name="addItem" type="button" class="btn btn-outline-primary">+ Add Item</button>
        <button type="submit" class="btn btn-success" formnovalidate>Save</button>
    {{ form_end(form) }}
</div>
Item Priority