Ответ 1
После прочтения большого количества документации я нашел решение моей проблемы здесь: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data
Чтобы сделать объект не требуемым, вы должны добавить слушателя событий и установить данные как отправку с нулевым сообщением.
Первый шаг
Добавьте параметр orphanRemoval=true
к вашему атрибуту
/**
* @ORM\OneToOne(targetEntity="AppBundle\Entity\Member", orphanRemoval=true, cascade={"persist", "remove"})
* @ORM\JoinColumn(name="parent2_id", referencedColumnName="id",nullable=true)
*/
private $parent2;
Второй шаг
Добавить новое поле в вашу форму, не отображаемый флажок
$builder
->add('parent1', MemberType::class)
->add('withParent2', CheckboxType::class, [
'mapped' => false,
'required' => false,
'data' => true
])
->add('parent2', MemberType::class, [
'required' => false
])
Мы будем использовать этот флажок, чтобы установить parent2 в null, если не отмечен.
Рядом с этим добавьте слушателей событий:
//this event will set whether or not the checkbox should be checked
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$family = $event->getData();
if ($family->getId()) {
$form->add('withParent2', CheckboxType::class, [
'mapped' => false,
'required' => false,
'data' => $family->getParent2() ? true : false
]);
}
});
//Event when the form is submitted, before database update
$builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
//if the checkbox was not checked, it means that there was not a second parent
$withParent2 = $event->getForm()->get('withParent2')->getData();
if (!$withParent2) {
// we set this attribute to null, and disable the form validation
$event->getData()->setParent2(null);
$event->stopPropagation();
}
}, 900);
Третий шаг
Наша форма работает нормально, единственная проблема - проверка javascript.
Просто выполните функцию jquery, которая удалит требуемый атрибут из ваших полей.
function toggleParent2Requirement(checked){
if (!checked) {
$("[id^=family_parent2]").prop("required", false);
$("[id^=family_parent2]").attr('disabled', true);
}
else {
$("[id^=family_parent2]").prop("required", true);
$("[id^=family_parent2]").attr('disabled', false);
}
}
Здесь вы делаете одностороннее отношение необязательным. Единственная часть, которой я не горжусь, это часть stopPropagation
. Это было в документации, и я не знаю, можем ли мы только отключить эту проверку поля более чистым способом.