在Ubuntu16.04上使用PhpStorm.2016.3.2和Symfony3
我有一个与名为Restaurant
的实体相关的FormType.php。
在这个实体中,我有一个名为city_id
的外键与一个名为city
的实体相连。
所以在我的FormType中,我实际上成功地使用EntityType::class
来调用我的城市实体:
->add('city', EntityType::class, array(
'class' => 'AppBundle:City',
'choice_label' => 'name',
))
这实际上有效,我的页面上出现button
,我可以从我的数据库中选择我的城市。
但我遇到了一个小问题。如果我的用户想要添加像Amsterdam
这样的新城市,该怎么办?
我如何在FormType.php
我的实体city
?
答案 0 :(得分:2)
我建议您在表单类型中使用事件侦听器/订阅者。你可以看看how to dynamically modify forms using form events。
如何处理:当用户在您选择的字段中选择一个名为" city"然后,监听器/订户添加文本字段以允许用户写入城市名称。
因此,在您的表单类型中,您可以添加如下事件订阅者:
$builder->addEventSubscriber(new CityFieldSubscriber($builder->getFormFactory(), 'city', $options['manager']);
请注意,您需要将实体管理器作为表单类型的选项传递。
然后创建订阅者(这是一个示例。我没有执行此代码,因此可能存在错误):
class CityFieldSubscriber implements EventSubscriberInterface
{
protected $factory;
protected $fieldName;
protected $listenedFieldName;
protected $repository;
protected $optionId;
public function __construct(FormFactoryInterface $factory, ObjectManager $manager)
{
$this->factory = $factory;
$this->fieldName = 'cityName'; // text field to add
$this->listenedFieldName = 'city'; // entity field to listen
$this->repository = $manager->getRepository('AppBundle:City');
$this->optionId = 0; // The value of the option in your select field
}
public static function getSubscribedEvents()
{
return [
FormEvents::POST_SET_DATA => 'postSetData',
FormEvents::PRE_SUBMIT => 'preSubmit'
];
}
private function addCityForm(FormInterface $form, City $city = null)
{
if (null !== $city) {
if ($city->getId() === $this->optionId) {
$form->add($this->fieldName, TextType::class, [
'label' => 'app.form.type.cityName.label',
'required' => true
]);
}
}
}
public function postSetData(FormEvent $event)
{
$city = $event->getForm()->get($this->listenedFieldName)->getData();
if ($city) {
$this->addCityForm($event->getForm(), $city);
} else {
$this->addCityForm($event->getForm());
}
}
public function preSubmit(FormEvent $event)
{
$data = $event->getData();
if (isset($data[$this->listenedFieldName]) && $data[$this->listenedFieldName] !== '') {
$this->addCityForm($event->getForm(), $this->repository->find($data[$this->listenedFieldName]));
}
if (!isset($data[$this->listenedFieldName])) {
$this->addCityForm($event->getForm());
}
}
}
之后,您需要编写一些javascript代码以在必要时添加文本字段。见这个例子:
<script>
var form = $('#form');
var formUrl = '{{ url('app_front_form') }}';
function replaceIfExistsOrRemove(selector, beforeSelectors, dom) {
var $new = $(dom).find(selector).parent('.form-group');
if ($new.length == 0) {
$(selector).parent('.form-group').remove();
} else {
if ($(selector).length > 0) {
$(selector).parent('.form-group').replaceWith($new);
} else {
for (i in beforeSelectors) {
if ($(beforeSelectors[i]).length > 0) {
$(beforeSelectors[i]).parent('.form-group').after($new);
return;
}
}
}
}
}
form.on('change', '#form_city', function() {
$('#form_submit_button').prop('disabled', true);
$.get(formUrl, $form.serialize(), function(html) {
$('#form_submit_button').prop('disabled', false);
replaceIfExistsOrRemove('#form_cityName', ['#form_city'], html);
});
});
</script>
提交表单后,如果表单有效,则保存此新城市并将其设置在您的实体中。
我希望这会对你有所帮助:)。