I recently build a DataTransformer that will accept a variety of different date formats in the end (like 12/12/2012 or 12.12.2012 or 2012-12-12).
My question is: before I had the date and time split up into two different fields:
$builder->add('date_end', 'datetime', array(
'label' => 'Date/Time',
'date_widget' => 'single_text',
'time_widget' => 'single_text',
'date_format' => 'dd.MM.yyyy',
'with_seconds' => false,
'required' => false,
) )
Which worked fine. How can I accomplish this with the new DataTransformer?
public function buildForm(FormBuilder $builder, array $options) {
builder->add('date_end', 'dateTime', array(
'label' => 'Date/Time',
'required' => false,
) )
}
class DateTimeType extends AbstractType {
private $om;
public function __construct(ObjectManager $om) {
$this->om = $om;
}
public function buildForm(FormBuilder $builder, array $options) {
$transformer = new DateTimeTransformer($this->om);
$builder->appendClientTransformer($transformer);
}
public function getDefaultOptions(array $options) {
return array(
'invalid_message' => 'TODO INVALID',
);
}
public function getParent(array $options) {
return 'text';
}
public function getName(){
return 'dateTime';
}
}
/**
* @param \DateTime|null $dateTime
* @return string|null
*/
public function transform($dateTime) {
if (null === $dateTime) {
return null;
}
return $dateTime->format('Y-m-d H:i');
}
/**
* @param string $value
* @return string|null
*/
public function reverseTransform($value)
{
if ( (null === $value) || empty($value) ) {
return null;
}
return new \DateTime( $value );
}
I'm assuming you are using Symfony 2.0. I've read that form component has changed somewhat in 2.1.
I had a similar problem - I wanted to have a datetime field that uses separate widgets for date and time (hour) input.
First of all, you have to create a separate form type for this field (which actually is a form in itself).
My code looks similar to this (altered for this example):
class MyDateTimeType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('date', 'date', array(
'label' => 'label.form.date',
'input' => 'datetime',
'widget' => 'single_text',
'format' => 'yyyy-MM-dd',
'error_bubbling' => true
))
->add('time', 'time', array(
'label' => 'label.form.time',
'input' => 'datetime',
'widget' => 'choice',
'error_bubbling' => true
));
$builder->appendClientTransformer(new DateTimeToDateTimeArrayTransformer());
}
public function getDefaultOptions(array $options)
{
return array(
'label' => 'label.form.date',
'error_bubbling' => false
);
}
public function getParent(array $options)
{
return 'form';
}
public function getName()
{
return 'my_datetime';
}
}
As you can see it is a form (don't let it confuse you) but we will use it as a single logical field. That's where the data transformer comes in. It has to split a single DateTime instance into date and time to obtain data for the two subfields when displaying the form and vice-versa when the form is submitted.
The error_bubbling settings ensure that the errors generated by subfields attach to our new subfield and don't propagate to the top-level form, but you may have diferrent goal.
My data transformer looks like this:
class DateTimeToDateTimeArrayTransformer implements DataTransformerInterface
{
public function transform($datetime)
{
if(null !== $datetime)
{
$date = clone $datetime;
$date->setTime(12, 0, 0);
$time = clone $datetime;
$time->setDate(1970, 1, 1);
}
else
{
$date = null;
$time = null;
}
$result = array(
'date' => $date,
'time' => $time
);
return $result;
}
public function reverseTransform($array)
{
$date = $array['date'];
$time = $array['time'];
if(null == $date || null == $time)
return null;
$date->setTime($time->format('G'), $time->format('i'));
return $date;
}
}
Finally you can use it like that:
$builder->add('startDate', 'my_datetime', array(
'label' => 'label.form.date'
));
You have to register it as a service to use it by alias, otherwise instantiate it directly (new MyDateTimeType()).
This may not be the prettiest solution but so is the form component in Symfony 2.0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With