>我创建了一个自定义表单字段类型"持续时间",以及 2 个字段"小时"和"分钟"
class DurationType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults([]);
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('hours', new DurationSmallType(), [])
->add('minutes', new DurationSmallType(), [])
;
}
public function finishView(FormView $view, FormInterface $form, array $options)
{
}
public function getName()
{
return 'duration';
}
}
持续时间小类型:
class DurationSmallType extends AbstractType
{
public function getName()
{
return 'duration_small';
}
}
两种类型的模板:
{% block duration_small_widget -%}
<div class="input-group" style="display: inline-block;width:100px;height: 34px;margin-right: 20px;">
<input type="text" {{ block('widget_attributes') }} class="form-control" style="width:50px;" {% if value is not empty %}value="{{ value }}" {% endif %}>
<span class="input-group-addon" style="height: 34px;"></span>
</div>
{%- endblock duration_small_widget %}
{% block duration_widget -%}
{{ form_widget(form.hours) }}
{{ form_widget(form.minutes) }}
{%- endblock duration_widget %}
在以分钟为单位保存的实体持续时间(作为整数)中,我在表单构建器中创建了一个数据转换器:
class EventType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$dataTransformer = new DurationToMinutesTransformer();
$builder
->add('name', NULL, array('label' => 'Название'))
->add('type', NULL, array('label' => 'Раздел'))
->add($builder
->create('duration', new DurationType(), array('label' => 'Продолжительность'))
->addModelTransformer($dataTransformer)
)
->add('enabled', NULL, array('label' => 'Включено'));
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TourConstructor'MainBundle'Entity'Event',
'csrf_protection' => true,
'csrf_field_name' => '_token',
'intention' => 'events_token'
));
}
/**
* @return string
*/
public function getName()
{
return 'mybundle_event';
}
}
持续时间到分钟变压器:
class DurationToMinutesTransformer implements DataTransformerInterface
{
public function transform($value)
{
if (!$value) {
return null;
}
$hours = ceil($value / 60);
$minutes = $value % 60;
return [
"hours" => $hours,
"minutes" => $minutes
];
}
public function reverseTransform($value)
{
if (!$value) {
return null;
}
return $value["hours"]*60 + $value["minutes"];
}
}
转换 - 工作,我在编辑字段中有小时和分钟,但反向转换不起作用,提交后我将持续时间字段作为数组。
符号错误:
Symfony'Component'Validator'ConstraintViolation
Object(Symfony'Component'Form'Form).children[duration].children[hours] = 3
Caused by:
Symfony'Component'Form'Exception'TransformationFailedException
Compound forms expect an array or NULL on submission.
Symfony'Component'Validator'ConstraintViolation
Object(Symfony'Component'Form'Form).children[duration].children[minutes] = 0
Caused by:
Symfony'Component'Form'Exception'TransformationFailedException
Compound forms expect an array or NULL on submission.
求求你,帮帮我。
我发现错误,DurationSmallType 需要选项 compound=false,默认值为 true,symfony 尝试使用我的 2 字段作为内部形式。我从实体窗体中删除模型转换器并将其放置在持续时间类型中。
我的表单构建器的最终代码:
事件类型:
class EventType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$dataTransformer = new DurationToMinutesTransformer();
$builder
->add('name', NULL, array('label' => 'Название'))
->add('type', NULL, array('label' => 'Раздел'))
->add($builder
->create('duration', new DurationType(), array('label' => 'Продолжительность'))
->addModelTransformer($dataTransformer)
)
->add('enabled', NULL, array('label' => 'Включено'));
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TourConstructor'MainBundle'Entity'Event',
'csrf_protection' => true,
'csrf_field_name' => '_token',
'intention' => 'events_token'
));
}
/**
* @return string
*/
public function getName()
{
return 'mybundle_event';
}
}
持续时间类型:
class DurationType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'html5' => true,
'error_bubbling' => false,
'compound' => true,
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('hours', new DurationSmallType(), [
"label"=>"ч."
])
->add('minutes', new DurationSmallType(), [
"label"=>"мин."
])
->addViewTransformer(new DurationToMinutesTransformer())
;
}
public function finishView(FormView $view, FormInterface $form, array $options)
{
}
public function getName()
{
return 'duration';
}
}
持续时间小类型:
class DurationSmallType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'compound' => false,
));
}
public function getName()
{
return 'duration_small';
}
}