I can't find an answer to the problem I'm facing and I wonder if it's something simple that I'm missing. Also, I am quite new to Symfony framework and didn't get the chance to learn everything yet.
I'm using Symfony 5.1
The Problem: TL;DR
My main task was to create a custom form_widget, so that I could write my own HTML for what I need to show. After some digging and going through the Symfony's documentation I was finally able to achieve that, but this caused another issue. Now, when I submit the form, the field for which I created the custom form_widget is missing from the submitted data.
Below there is more explanation on what and how I tried to solve this problem. Thanks in advance to anyone reading this and wanting to give me some directions.
Form:
$builder
->add('newUsers', CollectionType::class, [
'entry_type' => UserType::class, //Embedded Form
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'mapped' => false
])
->add('users', CollectionType::class, [
'entry_type' => UserType::class,
'allow_delete' => true,
'by_reference' => false,
'mapped' => true
]);
As you can see, I am using an embedded form twice for users. One of them allows me to add new Users to the Form (and has different HTML structure). The other one displays all users added at the previous step (Different part of the process).
I thought the problem may be with using the same embedded form twice, but when I don't use my custom widget, everything work as expected (just with the standard HTML).
My custom widget is in a separate Form Theme file and contains only this (the naming of the block is correct):
{% block _invitation_users_widget %}
{% for user in value %}
<tr>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
<td class="text-center">
<a href="#">
<i class="fas fa-user-minus"></i>
</a>
</td>
</tr>
{% endfor %}
{% endblock %}
Finally, I use this block after importing a form theme in the actual form html.twig file, like so:
{% form_theme form 'path/to/theme' %}
<table>
<thead>
<th>Name</th>
<th>Email</th>
<th></th>
</thead>
<tbody>
{{ form_widget(form.users) }}
</tbody>
</table>
This displays everything exactly as I want, but when the form gets submitted the expected 'users' array is missing from the submitted data (and this is tested in FormEvent::PRE_SUBMIT event listener, as well as in the Controller itself).
Now, when I remove the custom widget and use standard form_widget, the data is not missing, but I have input fields in my table (rather than just text).
Some things I tried already:
- Create a custom widget just for the name and an e-mail, rather than the whole User itself. The data was missing regardless.
- In FormEvent::PRE_SUBMIT I got access to Form variable and I got 'users' from there. Then I appeded this to the event data (the one submitted). This way I had access to 'users' inside my Controller, but the Form data was always giving me all the users (without the users I have deleted from the table) - so this is also no good.
The code was like this:
$form = $event->getForm();
if (! array_key_exists('users', $invitation)) {
$users = $form->get('users')->getData()->toArray();
$previousUsers = [];
foreach ($users as $user) {
$previousUsers[] = [
'name' => $user->getName(),
'email' => $user->getEmail()
];
}
$invitation['users'] = $previousUsers;
}
This is how the table looks like without creating a custom widget:
Rather than showing just the values, it shows input fields.
At this point I don't know what am I missing, and I can't find an answer in the Symfony documentation, here, or even symfonycasts. Any help will be appreciated.