Я пытаюсь создать форму, которая создает новое уведомление, которое может быть связано с:
- Существующим Vecino
- Новым Vecino
- Нетиз вышеупомянутого
И Vecino связан с Domicilio
Также у меня есть ModeloImpresion, который зависит от поля Area (оба из Notificacion)
Что я хочучтобы сделать это форма, где я создаю Notificacion с полем Area, который изменяет поле ModeloImpresion.Итак, я выполнил шаги на https://symfony.com/doc/3.4/form/dynamic_form_modification.html#form-events-submitted-data
Если я создаю один без Vecino, он работает, если я создаю новый Vecino, он работает, но когда мне нужно создать его с существующим Vecino, AJAX завершается неудачей со следующим исключениемпри обработке запроса (у сущностей есть другие поля, не связанные с ошибкой, поэтому я их не копировал):
Type error: Argument 1 passed to Proxies\__CG__\Brown\TurnoBundle\Entity\Vecino\Domicilio::setCalle() must be of the type string, null given, called in /home/gonchi/web/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php on line 623
Я проверял, и если я сбрасываю Notificacion, он имеет правильное Vecino с правильным Domicilioэто определил колл.
Я не знаю, где это идет не так
Схема отношений:
class Notificacion
{
/**
* @var null|Vecino
*
* @ORM\ManyToOne(targetEntity="Brown\TurnoBundle\Entity\Vecino")
*/
private $vecino;
/**
* @var Area|null
*
* @ORM\ManyToOne(targetEntity="Brown\BrownBundle\Entity\Area")
*/
private $area;
/**
* @var DatosFijos\ModeloImpresion|null
*
* @ORM\ManyToOne(targetEntity="Brown\BrownBundle\Entity\DatosFijos\ModeloImpresion")
*/
private $modeloImpresion;
}
class Vecino
{
/**
* @var null|Domicilio
*
* @ORM\ManyToOne(targetEntity="Brown\TurnoBundle\Entity\Vecino\Domicilio", cascade={"persist", "remove"})
*/
private $domicilio;
}
Вот мой контроллер:
/**
* @param Request $request
*
* @return Response|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function nuevoAction(Request $request)
{
// This comes from a search on the repository.
// If it finds a Vecino it returns the object.
// If it didn't find one it returns null.
// If this Notificacion shouldn't have a Vecino it returns false
$vecino = $this->getSessionVariable(Constants::SESSION_VECINO);
$notificacion = new Notificacion();
// If there should be a Vecino but didn't find one it creates one
if ($vecino === null) {
$vecino = new Vecino();
$vecino->setDni($this->getSessionVariable(Constants::SESSION_DNI_CUIL));
}
// If there's a Vecino (existing or new) it sets it to the Notificacion
if ($vecino) {
$notificacion->setVecino($vecino);
}
$form = $this->createForm(NuevoType::class, $notificacion);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// A shortcut to $this->getEm()->persist()
$this->saveToDatabase($notificacion);
return $this->redirectToRoute('admin_notificacion_listado');
}
return $this->render('@Admin/Notificacion/nuevo.html.twig', [
'form' => $form->createView(),
]);
}
Имоя форма:
class NuevoType extends AbstractType
{
/**
* @var AreaRepository|\Doctrine\ORM\EntityRepository
*/
private $areaRepository;
/**
* @var \Brown\BrownBundle\Repository\DatosFijos\ModeloImpresionRepository | \Doctrine\ORM\EntityRepository
*/
private $modeloImpresionRepository;
public function __construct(EntityManager $entityManager)
{
$this->areaRepository = $entityManager->getRepository(Area::class);
$this->modeloImpresionRepository = $entityManager->getRepository(ModeloImpresion::class);
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Check so it only add it if there should be one
if ($builder->getData()->getVecino()) {
$builder->add('vecino', VecinoMinimoType::class, [
'label' => false,
]);
}
$builder
->add('area', EntityType::class, [
'class' => Area::class,
'choice_label' => 'nombre',
'query_builder' => function (AreaRepository $er) {
return $er->createQueryBuilder('a')
->orderBy('a.nombre', 'ASC');
},
'placeholder' => 'Seleccione el área',
'attr' => ['class' => 'area-entity']
])
->add('submit', SubmitType::class, [
'label' => 'Guardar',
'attr' => ['class' => 'btn btn-primary'],
])
;
$formModifier = function (FormInterface $form, Area $area = null) {
$modelosImpresion = null === $area ? [] : $this->modeloImpresionRepository->findByAreas([$area]);
$form->add('modeloImpresion', EntityType::class, [
'label' => 'Tipo de Notificación',
'class' => ModeloImpresion::class,
'choices' => $modelosImpresion,
'attr' => ['class' => 'modeloImpresion-entity'],
]);
};
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formModifier) {
/** @var Notificacion $notificacion */
$notificacion = $event->getData();
$form = $event->getForm();
$formModifier($event->getForm(), $notificacion->getArea());
});
$builder->get('area')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$area = $event->getForm()->getData();
$formModifier($event->getForm()->getParent(), $area);
}
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefaults([
'data_class' => Notificacion::class,
]);
}
}
и наконец Javascript на мой взгляд:
<script>
var area = $('.area-entity');
area.change(function() {
var form = $(this).closest('form');
var data = {};
data[area.attr('name')] = area.val();
$.ajax({
url : form.attr('action'),
type: form.attr('method'),
data : data,
success: function(html) {
var modeloImpresion = $('.modeloImpresion-entity');
modeloImpresion.replaceWith(
$(html).find('.modeloImpresion-entity')
);
},
});
});
</script>