Symfony2: динамическая форма, использующая события формы

У меня есть некоторые проблемы, чтобы сделать динамическая форма в моем Symfony2 проект. Я стараюсь следовать документам Вот, но трудно понять, как на самом деле поступить с этим. Я пытаюсь иметь такую ​​форму на страница.

Действительно, мне нужно создать динамическую форму где выпадающий список динамически меняет свои значения, когда значение выбирается из выпадающего списка до.

Эта динамическая форма включает в себя 4 объекта:

Parcsimmobilier.php <знак равно ManyToOne Ensembles.php <знак равно
ManyToOne Batiments.php <знак равно ManyToOne Zonestechnique.php

1- первый допад касается Парк, когда я выбираю значение в этом раскрывающемся списке, появляется раскрывающийся список ансамблей. Значения выпадающего ансамбля должны принадлежать на парки я выбираю первым.

2 — второй выпадающий список со значением ансамбля: когда я выбрал значение, появляется третий выпадающий список, который касается категории моих зон (юридическое лицо Zonestechnique).

3 — раскрывающиеся категории зон имеют множественный выбор, но когда я выбираю значениевне«, появляется последний выпадающий список со значениями batiments, но со значением» none «неизбежно. Но если я выберу другие значения чем «снаружи», выпадающий список batiments появляется со всеми batiments (принадлежат ансамблю, который я выбираю раньше).

4 — когда я делаю все эти шаги, появляется остальная часть формы (форма для сущности техники зон)

Я должен заполнить эту форму, когда я хочу добавить / создать новую технику зон в моей базе данных.

Вот код для моего entities:

//Parcsimmobilier entity
class Parcsimmobilier
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;

/**
* @var string
*
* @ORM\Column(name="nom", type="string", length=150, nullable=false)
*/
private $nom;

/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="Ensembles", mappedBy="parcsimmobilier")
*/
private $ensembles;
//end of Parcsimmobilier entity//Ensembles entity
class Ensembles
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;

/**
* @var string
*
* @ORM\Column(name="nom", type="string", length=150, nullable=false)
*/
private $nom;

/**
* @var \Parcsimmobilier
*
* @ORM\ManyToOne(targetEntity="Parcsimmobilier")
* @ORM\JoinColumns({
*   @ORM\JoinColumn(name="parcsimmobilier_id", referencedColumnName="id")
* })
*/
private $parcsimmobilier;
//end of Ensembles entity//Batiments entity
class Batiments
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;

/**
* @var string
*
* @ORM\Column(name="nom", type="string", length=150, nullable=true)
*/
private $nom;

/**
* @var \Ensembles
*
* @ORM\ManyToOne(targetEntity="Ensembles")
* @ORM\JoinColumns({
*   @ORM\JoinColumn(name="ensembles_id", referencedColumnName="id")
* })
*/
private $ensembles;
//end of Batiments entity//Zonestechnique entity
class Zonestechnique
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;

/**
* @var string
*
* @ORM\Column(name="nom", type="string", length=150, nullable=false)
*/
private $nom;

/**
* @var \Batiments
*
* @ORM\ManyToOne(targetEntity="Batiments")
* @ORM\JoinColumns({
*   @ORM\JoinColumn(name="batiments_id", referencedColumnName="id")
* })
*/
private $batiments;

/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Categorieszonestechnique")
* @ORM\JoinTable(name="zonestechnique_categorieszonestechnique",
*   joinColumns={
*     @ORM\JoinColumn(name="zonestechnique_id", referencedColumnName="id")
*   },
*   inverseJoinColumns={
*     @ORM\JoinColumn(name="categorieszonestechnique_id", referencedColumnName="id")
*   }
* )
*/

private $categorieszonestechnique;

После документа это мой тип, ZonesTechniqueType.php:

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

class ZonestechniqueType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('parcsimmobilier', 'entity', array(
'class'    => 'EnexgirDatabaseBundle:Parcsimmobilier',
'property' => 'nom',
'multiple' => false,
'required' => true,
'mapped' => false,
'empty_value' => '-- sélectionner un parc --',
'label'    => 'Choisir le parc immobilier : ',
'attr' => array('class' => 'col-xs-3 form-control')))
->add('nom')
->add('localisation')
->add('commentaire')
->add('categorieszonestechnique')
->add('batiments');

$formModifier = function (FormInterface $form, Parcsimmobilier $parc = null) {
$ensembles = null === $parc ? array() : $parc->getEnsembles();

$form->add('ensembles', 'entity', array(
'class'       => 'EnexgirDatabaseBundle:Ensembles',
'property' => 'nom',
'multiple' => false,
'required' => true,
'mapped' => true,
'empty_value' => '-- sélectionner un ensemble --',
'label'    => 'Choisir l\'ensemble : ',
'query_builder' => function(EntityRepository $er) use ($parc) {
return $er->createQueryBuilder('e')
->where("e.parcsimmobilier = :parcsimmobilier_id")
->orderBy('e.nom', 'ASC')
->setParameter(':parcsimmobilier_id', $parc);
},
));
};

$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity
$data = $event->getData();

$formModifier($event->getForm(), $data->getEnsembles());
}
);

$builder->get('parcsimmobilier')->addEventListener(
FormEvents::POST_SUBMIT,

Это метод контроллера, который я использую для:

public function addZonesConformitesAction(Request $request) {

$em=$this->getDoctrine()->getManager();
$zoneConformite = $em->getRepository('EnexgirDatabaseBundle:Zonestechnique');

$zoneConformite = new Zonestechnique;
$form=$this->createForm(new ZonestechniqueType(), $zoneConformite);

$form->handleRequest($request);

//instruction if à plusieurs conditions: ici si la method est POST et si le formulaire est valide
if ($request->isMethod('POST') | ($form->isValid())) {

$form->bind($request);
$zoneConformite = $form->getData();

$em->persist($zoneConformite);
$em->flush();

return $this->redirect($this->generateUrl('indexRechercheZones'));
}

//retourner le formulaire d'ajout si c'est invalide
else {
return $this->render('EnexgirGestionEquipementsTechniquesBundle:ZonesTechnique:ajouterZonesTechniqueConformites.html.twig', array('form' => $form->createView() ));
}
}

И наконец, блок содержимого моей ветки:

{% block content %}
<div class="panel-heading">
<h3 class="panel-title"> Gestion Des Zones techniques -<small>&nbsp;&nbsp;(ajout)</small></h3>
</div>
{# Panel Body #}
<div class="panel-body">
{# Menu #}
<div class="panel-body">
<ul class="nav nav-tabs">
<li role="presentation">
<a href="{{ path('indexRechercheZones') }}">Visualisation des Zones techniques</a>
</li>
<li role="presentation" class="active">
<a>Ajouter une Zone technique et ses Conformités</a>
</li>
</ul>
</div>
{# Formulaire #}
<div class="page-header">
<h4><b><u>Ajouter une zone technique et ses conformites</u></b><small>&nbsp;&nbsp;(créer une zone technique qui n'existe pas encore, ainsi que ses conformités respectives)</small></h4>
<br>
<form action="{{ path('ajouterZonesConformites_process') }}" method="POST" {{ form_enctype(form) }}>
<div>
{{ form_start(form) }}
{{ form_row(form.parcsimmobilier) }}    {# <select id="meetup_sport" ... #}
{{ form_row(form.ensembles) }} {# <select id="meetup_position" ... #}
{{ form_end(form) }}
{# validation #}
<input type="submit" value="Ajouter" class="btn btn-success"/>
</div>
<br>
</form>
</div>
</div>
{% endblock %}

Пока я не представил Код Ajax в моей веточке, потому что у меня есть это ошибка:

Попытка вызвать метод «getEnsembles» в классе
«Enexgir \ DatabaseBundle \ Entity \ Zonestechnique» в
C: \ WAMP \ WWW \ MyPathToMyProject \ SRC \ Enexgir \ DatabaseBundle \ Form \ ZonestechniqueType.php
строка 65

Это код для строки 65:

$formModifier($event->getForm(), $data->getEnsembles());

Я это понимаю Ensembles.php а также Parcsimmobilier.php не имеет никакого отношения к Zonestechnique.php, но я следую за документом, и я не очень понимаю, как это работает. Кто-то может помочь мне понять и сделать эту форму?

Заранее спасибо.

2

Решение

Система событий форм Symfony может, конечно, использовать некоторую оптимизацию. При этом, это возможно сделать. Для каждого выпадающего списка вам понадобятся 2 события формы (PRE_SET_DATA / POST_SUBMIT). Вы должны быть в состоянии объединить все ваши события PRE_SET_DATA в одну функцию, но вам придется обрабатывать события POST_SUBMIT в отдельных функциях, поскольку они связаны с формой

Вам нужно будет изменить свое заявление if на:

if($request->isMethod('POST') && !$request->isXmlHttpRequest() && $form->isValid())

Вам также не нужно звонить:

$form->bind($request);

если вы уже звонили:

$form->handleRequest($request);

Последнее является заменой первого.

Только «обрабатывая» форму для запросов не AJAX, это позволит вашей форме получать обновленные данные, запускать события формы и возвращать их.

1

Другие решения

@Chausser сделал хорошую мысль, так как в вашем коде в этом разделе $formModifier($event->getForm(), $data->getEnsembles()); Вы прошли экземпляр Ensembles так что не нужно звонить $data->getEnsembles() снова.
Надеюсь, поможет

0

По вопросам рекламы [email protected]