Skip to content

Symfony LiveComponent: syncing child form data to parent component #3411

@davidvancl

Description

@davidvancl

Hello,

first of all, I wanted to ask this on Slack, but the link you have on https://ux.symfony.com/support is no longer active. That’s just an FYI, and now to my question.

I’m dealing with a situation that seems standard to me, but I haven’t been able to find a proper solution in your documentation. For context, I’m using a Symfony live form to collect invoice details for user. However, I also want to use this form for user registration. So I need to move the form submission logic into some parent component and leave this “form” only as a dummy that renders the fields while validation still works on it. That wouldn’t be such a problem. The problem is how to update the parent form that will handle the submission.

I’ve created a test example so far:

Parent PHP component:

#[AsLiveComponent(template: '...')]
class View extends BaseComponent
{
    #[LiveProp(writable: ['invoiceAddress.city'])]
    public RegisterState $state;
    ....
    #[LiveAction]
    public function submit(): void
    {
        $tmp = 0;
    }
}

Parent TWIG template:

<div {{ attributes }}>
   <twig:Registration:TestForm data-model="state.invoiceAddress:address"/>
   <button type="button" data-action="live#action" data-live-action-param="submit">Submit</button>
</div>

Child form component that updates the parent state.

#[AsLiveComponent(template: '...')]
class TestForm extends BaseComponent
{
    use DefaultActionTrait;

    #[LiveProp(writable: ['city'])]
    public InvoiceAddress $address;
}

Child TWIG template:

<div {{ attributes }}>
   <input type="text" data-model="on(change)|address.city">
</div>

This example doesn’t work when I work with the InvoiceAddress object. If I pass a plain city string into TestForm, then updating the object on the parent component works normally.
Ideally, TestForm should be a Live form that renders its inputs using a FormType. However, I haven’t been able to figure out how to update the whole object without mapping all the InvoiceAddress values individually.
The only solution I found was to emit an event to the parent component and then update it there. But that feels like overkill to me. I’m basically dealing with nested forms, even though a form inside a form is of course not possible from an HTML point of view. So my question is also about how to correctly break the form into sub-objects that will handle filling data into the main form, while still being able to use the Live form mechanism that handles rendering inputs, validation messages, and so on.

Please guide me on the correct approach, or how to fix the example so it works. And I apologize if this is a silly question.

Thank you for any advice.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions