Symfony DateTime format errors - datatransformation (external datepicker) - symfony

I'm working with Symfony 6 and a TempusDomini datepicker.
I have read (amongst many others) the symfony documentation, https://symfony.com/doc/current/reference/forms/types/datetime.html.
Based on the documentation I found I initially implemented the form builder as followed:
->add('TextDateField')
->add('RegistrationDateTime', DateTimeType::class, [
'required' => false,
'widget' => 'single_text',
'format' => 'm/d/Y, h:i a',
'attr' => [
'class' => 'datetimepicker-input',
'data-target' => '#datetimepicker1'
],
'html5' => false,
])
The "TextDateField" is for troubleshooting, see explanation below.
And the actual TWIG file looks like this (for the TextDateField I have a similar datapicker block as the one for RegistrationDateTime):
{{form_start(form)}}
{{form_row(form.username)}}
<div class>
<label for="datetimepicker1Input" class="form-label">Simple picker</label>
<div class="input-group" id="datetimepicker1" data-td-target-input="nearest" data-td-target-toggle="nearest">
<input id="user_creation_form_RegistrationDateTime" name="user_creation_form[RegistrationDateTime]" type="text" class="form-control" data-td-target="#datetimepicker1">
<span class="input-group-text" data-td-target="#datetimepicker1" data-td-toggle="datetimepicker">
<span class="fa-solid fa-calendar"></span>
</span>
</div>
<script type="text/javascript">
const picker = new tempusDominus.TempusDominus(document.getElementById('datetimepicker1'));
</script>
</div>
{{form_row(form.roles)}}
{{form_row(form._token)}}
{{form_row(form.submit)}}
What I notice is that the dates are correctly given from a datepicker to the controller if passed via Text.
Please see this dump where you can see 2 datepicker values as passed to the controller, both for the same dates (6 may 2022)
App\Entity\TUser^ {#361
-id: null
-username: "scdsqd"
-roles: array:2 [
0 => "ROLE_USER"
1 => "ROLE_ADMIN"
]
-TextDateField: "05/06/2022, 12:42 PM"
-RegistrationDateTime: DateTime #1640599500 {#828
date: 2021-12-27 11:05:00.0 Europe/Berlin (+01:00)
}
}
So as you can see the text is passed correctly for the "text" datepicker but using the symfony DateTimeType::class messes it up by giving a seemingly random date.
Using other formats as datetime (for example timestamp) is not possible.
So how can I pass the value correctly to the database?
One possible "solution" is to work with TextType::class but since I want to keep the field RegistrationDateTime in the database as a DateTimeType this is not the best solution either since that would mean I have to transform the data.
Maybe I'm not looking at the right place, but it seems to me as if Symfony is not well adjusted to use external datepickers.
I have found tons of post with people struggling to implement a datepicker...
Is the approach I use correct?
How can I "force" symfony to "understand" the datepicker provided dates?
If the only way is to use TextType in the form-builder, how do I tackle the datatransformations to make sure that via doctrine I save in the datetime format?
Any pointers in the right direction are welcome... I'm getting rather frustrated by it since I've struggled on it an embarrassingly long time now...

Related

Symfony EntityType Extended with Jquery Validate Plugin

I encounter a problem related to the use of the EntityType with the extended and multiple set to true (which generates checkboxes) and then validating each field separately (required or not) using the JqueryValidate plugin.
I'm using the automatic rules set by the class and attributes, so all fields work well but the checkboxes.
This happens because the validator uses the attribute name to set validation rules, but each validation rule is only applied once per name, so only the first checkbox is validated. This combined with the impossibility to change the names for the choices of an EntityType with extended and multiple, makes it impossible to use this configurations together.
CODE
FormType
$builder
->add('checkboxes', EntityType::class, [
'class' => MyClass::class,
'required' => false,
'expanded' => true,
'multiple' => true,
]);
Checkboxes rendered
<input type="checkbox" id="appbundle_myclass_checkboxes_1" name="appbundle_myclass[checkboxes][]" value="1">
<input type="checkbox" id="appbundle_myclass_checkboxes_2" name="appbundle_myclass[checkboxes][]" value="2" required="">
QUESTION
Is there a way to change the name attribute of those checkboxes so I can do multiple validations on them?
Or is there a workaround to make the validator work in these cases?

Symfony 4 - Organize layout of fields

Using Symfony 4, I wonder if there a simple way to organize the layout of how display my fields.
For now, I template everything in my views (to have 2 columns for example) :
<div class="row">
<div class="col-md-6">
{{ form_row(form.name) }}
</div>
<div class="col-md-6">
{{ form_row(form.company) }}
</div>
</div>
{{ form_rest(form) }}
But, I don't want to do this, I just want to render whole form in my view, and manage the template in my FormBuilder. I would like to write something like :
$builder
->add('<div class="row"><div class="col-md-6">', HtmlType::class)
->add('name', TextType::class, [
'label' => 'Nom'
])
->add('</div><div class="col-md-6">', HtmlType::class)
->add('company', TextType::class, [
'label' => 'Société cliente'
])
->add('</div></div>', HtmlType::class);
I looked at the documentation, but it's pretty poor, it shows how to inerhit from existing fields.
Is there a way to create this HtmlType to just handle simple Html tags ? or a better way ?
You should be able to do something like that :
$builder->add('your_field', YourFieldClass::class, [
'attr' => ['class' => 'your css class'],
]);
The best solution would be to create a custom form theme. Reference to the documentation is here. I haven't done this myself for creating custom grid but I guess you can create some custom type options using the OptionResolver that will tell your template how to organize your fields and then based on that you can organize your custom form theme however you want.

Symfony2 Form with collection type (many-to-many)

What I have
I have a database table "Teams" and a table "Players", connected with a Teams_has_Players table (many-to-many relationship). I generated my entities. I can now succesfully retrieve the players from a team by doing: $players = $team->getPlayers()->toArray();
What I'm trying to do
I'm trying to make a form where you can edit all of the team's player names and their position on the field. So I basically would like to have some rows with in each row an input field with the name and an input field with his location.
What I tried to do
So I read a lot about the Symfony2 Collection type and tried this:
$form = $this->createFormBuilder(null)
->add('name', 'text', array('label' => 'Name', 'data' => $team->getName()))
->add('players', 'collection', array('data' => $team->getPlayers()->toArray()))
->getForm();
In my view I tried this:
<ul>
{% for player in form.players %}
<li>
{{ form_widget(player.name) }}{{ form_widget(player.position) }}
</li>
{% endfor %}
</ul>
But I get this error:
The form's view data is expected to be of type scalar, array or an
instance of \ArrayAccess, but is an instance of class
MatchTracker\Bundle\AppBundle\Entity\Players. You can avoid this error
by setting the "data_class" option to
"MatchTracker\Bundle\AppBundle\Entity\Players" or by adding a view
transformer that transforms an instance of class
MatchTracker\Bundle\AppBundle\Entity\Players to scalar, array or an
instance of \ArrayAccess.
So I added 'data_class' => 'MatchTracker\Bundle\AppBundle\Entity\Players', but then I get an error that The form's view data is expected to be an instance of class MatchTracker\Bundle\AppBundle\Entity\Players, but is a(n) array. You can avoid this error by setting the "data_class" option to null
Anyone that can help me solve this problem? I just want to edit the team's player names/locations/.. in a form. If that works I'm going to extend the form so I can add/remove players.
This is what your are trying to do.

symfony2 comparing hidden field with its hash with form validation

I would like to know how to compare fields in symfony2 form with custom validation.
In particular I want to compare a simple hidden field with its hash.
<input type="hidden" name="smoke" value="1" />
<input type="hidden" name="smoke_hash" value="kahsjkdasjkdh3iuy84932798" />
Something like "repeated Field" but validated with my own logic.
But more something like this:
use Symfony\Component\Validator\Constraints\HashMatchString;
$builder
->add('smoke', 'hidden', array(
'data' => 1,
)
)
->add('smoke_hash', 'hidden', array(
'constraints' => array(
new HashMatchString('smoke')
),
)
)
;
Form Goodness in Symfony 2.1
I’ve already see the solution of Steven Brown (http://www.yewchube.com/2011/08/symfony-2-field-comparison-validator/) but is one year ago with multiple touches on core files...
SOLVED
I’ve created a gist: Gist
Just add validation method to your entity http://symfony.com/doc/current/book/validation.html#getters

Drupal Custom Module / Form Question: Adding an array of fields

I'm creating a custom module where I'd like to have the "add another item" functionality for a particular field, but I can't seem to figure out what I need to do in order to accomplish this... I've been going through Drupal forums and their Forms API Reference, but I must not be getting something.... I'm using Drupal 6.20, and in my module, I tried:
$form['options'] = array(
'#title' => t('Options'),
'#type' => 'fieldset',
);
$form['options']['address'] = array(
'#type'=>'textfield',
'#title'=>t('Address'),
'#tree' => 1,
);
Thinking I would get an text input that looked like this:
<input type="text" class="form-text text" value="" size="60" id="edit-address-0-value" name="address[0][value]">
But, I just get an input that looks like this:
<input type="text" class="form-text" value="" size="60" id="edit-address" name="address" maxlength="128">
You need to set #tree on the element above the one you want to duplicate. FAPI will store values in a tree structure from that element on downwards.
To get a name like address[0][value] you will need something like
$form['options']['address'] = array(
'#tree' => TRUE,
);
$form['options']['address'][0] = array(
'#tree' => TRUE,
);
$form['options']['address'][0]['value'] = array(
'#type'=>'textfield',
'#title'=>t('Address'),
);
But you don't need the [value] part unless you are actually trying to achieve multi-valued grouped fields or if your field has a complex (custom) data type implemented with multiple PHP values (ie. latitude/longitude, start/stop dates, etc.).
You will also probably need to store the number of values in something like $form['options']['#nb_values'] or in an hidden field (if you plan to add the additional fields to the form using JavaScript).

Resources