Symfony 3.4 为什么 formtype 的 CollectionType 没有 post 值

Symfony 3.4 Why CollectionType of formtype don't post values

我的表单的某些行有一个奇怪的问题。我无法在我的 collectionType 日期和我的 collectionType userIduser 中添加新行。

dates 是 InterventionHasDate

的集合类型

userIduser 是实体的集合类型:user

当我使用jquery添加新行时,它们被打印在HTML中但是当我post 没有已保存。 我试图转储我的表单的值,但好像 表单 中没有新值。 当我在数据库中手动输入新日期时,它们会被打印出来,我可以在我的页面中修改或删除它们。 我的表格:

{

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('idtypeinter',EntityType::class, [
            // looks for choices from this entity
            'class' => 'ssiplanificationBundle:Typeintervention',
            'label'=> 'Type de rendez-vous :',
            'choice_label' => 'nomtyperdv',
        ])
        ->add('Valider',SubmitType::class,['label'=>'Valider'])
        ->add('site',EntityType::class, [
            'class' => 'ssiplanificationBundle:Site',
            'choice_label' => 'nomSite',
            'label'=>'Site : ',
            'placeholder'=> 'Selectionnez votre site',
            'required'=>false,
            'mapped'=>false,
        ])->add('batiment',EntityType::class, [
            'class' => 'ssiplanificationBundle:Batiment',
            'choice_label' => 'nomBatiment',
            'label'=>'Batiment : ',
            'required'=>false,
            'mapped'=>false,
            'placeholder' => 'Veuillez choisir un batiment',
        ])->add('contactCorrespondant',EntityType::class, [
            'class' => 'ssiplanificationBundle:Contact',
            'choice_label' => 'nomContact',
            'label'=>'Contact à rencontrer sur site : ',
            'required'=>false,
        ]);


        $builder->add('installationIdinstallation',EntityType::class, [
            'class' => 'ssiplanificationBundle:Installation',
            'label'=> 'Installations :',
            'multiple' => true,
            'expanded' => true,
            'required'=> false,

        ])->add('visiteIdvisite',EntityType::class, [
           'class' => 'ssiplanificationBundle:Visite',
            'label'=> ' Visites :',
            'multiple' => true,
            'expanded' => true,
            'required'=> false,
        ])->add('AfficherplusInstallations',SubmitType::class,['label'=>'Afficher Plus'])

        ->add('AfficherplusVisites',SubmitType::class,['label'=>'Afficher Plus'])
        ->add('Validersite',SubmitType::class,['label'=>'Valider'])
        ->add('Validerbatiment',SubmitType::class,['label'=>'Valider'])
        ->add('numerointervention', TextType::Class,array('label'=> "Numéro d'intervention : ",'required'=>false))
        ->add('contactConfirmation',EntityType::class, [
             'class' => 'ssiplanificationBundle:Contact',
            'choice_label' => 'nomContact',
            'label'=>'Contact de confirmation par mail : ',
            'required'=>false,
        ])
        ->add('contactRdv',EntityType::class, [
            'class' => 'ssiplanificationBundle:Contact',
            'choice_label' => 'nomContact',
            'label'=>'Contact pour prise de rendez-vous téléphonique : ',
            'required'=>false,
        ])
        ->add('iduser',EntityType::class, [
            'class' => 'ssiplanificationBundle:User',
            'query_builder' => function (UserRepository $er) {
                return $er->createQueryBuilder('u')
                ->where('u.estTechnicien = :fonction')
                ->setParameter('fonction', 'Oui');
            },
            'choice_label' => 'username',
            'label'=>'Technicien : ',
        ])
         ->add('userIduser',CollectionType::class,[
            'entry_type' => EntityType::class,
            'entry_options' => [
                'class' => 'ssiplanificationBundle:User',
                'choice_label' => 'username',
                'label'=> false,
                'query_builder' => function (UserRepository $er) {
                    return $er->createQueryBuilder('u')
                    ->where('u.estTechnicien = :fonction')
                    ->setParameter('fonction', 'Oui');
                },
            ],
            'label'=>'Techniciens complémentaires :',
            'allow_add' => true,
            'allow_delete' => true,
        ])

        ->add('dates',CollectionType::class,[
            // looks for choices from this entity
            'entry_type' => InterventionHasDateType::class,
            'allow_add' => true,
            'allow_delete' => true,
            'label'=>"Jours(s) d'intervention :",
        ])
        ->add('nomstatut',EntityType::class, [
            // looks for choices from this entity
            'class' => 'ssiplanificationBundle:Statut',
            // uses the User.username property as the visible option string
            'choice_label' => 'nomStatut',
            'label'=>'Statut : ',
        ])
        ->add('commentaire',TextareaType::class,['label'=>'Commentaire :','required'=>false])
        ->add('Enregistrer',SubmitType::class,['label'=>'Enregistrer'])
        ;

        $builder->get('site')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) {
                $form=$event->getForm();
                $this->addCorrespondantField($event->getForm()->getParent(),$event->getForm()->getData());
                $this->addBatimentField($event->getForm()->getParent(),$event->getForm()->getData());
            }
        );
        $builder->addEventListener(
            FormEvents::POST_SET_DATA,
            function (FormEvent $event) {
                $data= $event->getData();
                $installations= $data ->getInstallationIdinstallation(); 
                $visites= $data ->getVisiteIdvisite();
                if($data->getIdtypeinter()=="Vérification")
                {
                    if(! $installations->isEmpty())
                    {
                        $batiment=$installations[0]->getZoneIdzone()[0]->getIdbatiment();
                    }else{
                        $batiment=NULL;
                    }

                }else{
                    if(! $visites->isEmpty())
                    {

                        $batiment=$visites[0]->getInstallationIdinstallation()->getZoneIdzone()[0]->getIdbatiment();
                    }else{
                        $batiment=NULL;
                    }

                }
                if($batiment != NULL){
                     $site=$batiment->getIdsite();
                }else{
                    $batiment=NULL;
                    $site=NULL;
                }


                if($site !=NULL){

                    $this->addCorrespondantField($event->getForm(),$site);
                    $this->addBatimentField($event->getForm(),$site);
                    $this->addInstallationField($event->getForm(),$batiment);
                    $event->getForm()->get('site')->setData($site);
                    $event->getForm()->get('batiment')->setData($batiment);
                    $event->getForm()->get('installationIdinstallation')->setData($installations);
                    $event->getForm()->get('visiteIdvisite')->setData($visites);
                    $event->getForm()->get('contactCorrespondant')->setData($data ->getContactCorrespondant() );

                }else{
                    $this->addCorrespondantField($event->getForm(),$site);
                    $this->addBatimentField($event->getForm(),$site);
                    $this->addInstallationField($event->getForm(),$batiment);
                }
            }
        );


    }

我的约会表格:

class InterventionHasDateType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('dateintervention',DateType::class,array(
            'widget' => 'single_text',     
            'label'=> 'Le'
            )
        )
        ->add('heuredebut',TimeType::class,array('widget' => 'single_text',    
        'attr'=> ['step'=> '900' ] ,    
        'label'=> 'De'))
        ->add('heurefin',TimeType::class,array('widget' => 'single_text',  
        'attr'=> ['step'=> '900' ] ,      
        'label'=> 'A'))
        ;
    }

我的控制器:

public function PlanificationInterventionModifyAction(Intervention $intervention=NULL, Request $request)
    {
        if($intervention==NULL){
            $intervention=new Intervention();
        }
        $originalDates =array();
        // Create an ArrayCollection of the current Date objects in the database
        foreach ($intervention->getDates() as $inter) {
            $originalDates[]=$inter;
        }

        $originalTech= array();
        // Create an ArrayCollection of the current Date objects in the database
        foreach ($intervention->getUserIdUser() as $tech) {
            $originalTech[]=$tech;
        }
        $originalVisite= array();
        // Create an ArrayCollection of the current Date objects in the database
        foreach ($intervention->getVisiteIdvisite() as $visite) {
            $originalVisite[]=$visite;
        }

        $form = $this->createForm(InterventionType::class, $intervention);

        $form->handleRequest($request); 

        if ($form->get('Enregistrer')->isClicked() and  $form->isValid()) {

            $em = $this->getDoctrine()->getManager();
            foreach ($originalVisite as $visite) {
                if (false === $form->get("visiteIdvisite")->getData()->contains($visite)) {
                    // if you wanted to delete the Tag entirely, you can also do that
                    $visite->removeInterventionIdintervention($intervention);
                    $em->persist($visite);
                }
            }
            foreach ($form->get("visiteIdvisite")->getData() as $visite) {

                if (!in_array($visite,$originalVisite)) {
                    $visite->addInterventionIdintervention($intervention);
                    $em->persist($visite);
                }
            }
            foreach ($originalTech as $tech) {
                if (false === $form->get("userIduser")->getData()->contains($tech)) {
                    // if you wanted to delete the Tag entirely, you can also do that
                    $tech->removeInterventionIdintervention($intervention);
                    $em->persist($tech);
                }
            }
            foreach ($form->get("userIduser")->getData() as $tech) {

                if (!in_array($tech,$originalTech)) {
                    $tech->addInterventionIdintervention($intervention);
                    $em->persist($tech);
                }
            }
            dump($form->get("dates"));
            dump($form->get("dates")->getData());

            foreach ($originalDates as $date) {
                if (false === $form->get("dates")->getData()->contains($date)) {
                    // if you wanted to delete the Tag entirely, you can also do that
                    $em->remove($date);
                }
            }
            foreach ($form->get("dates")->getData() as $date) {

                if (!in_array($date,$originalDates)) {

                    $date->setInterventionIdintervention($intervention);
                    $em->persist($date);
                }
            }

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

            $request->getSession()->getFlashBag()->add('notice', 'Enregistrement effectué.');


            //return $this->redirectToRoute('ssiplanification_planification_homepage');
        }
        return $this->render('planification/InterventionNew.html.twig', array(
            'form' => $form->createView()));
    } 

实体 InterventionHasDate:

/**
 * InterventionHasDate
 *
 * @ORM\Table(name="intervention_has_date", indexes={@ORM\Index(name="intervention_idIntervention", columns={"intervention_idIntervention"})}, 
 * uniqueConstraints={
 *   @ORM\UniqueConstraint(
 *     columns={"dateintervention", "HeureDebut","HeureFin","intervention_idIntervention"}
 *   )
 * })
 * @ORM\Entity(repositoryClass="ssi\planificationBundle\Repository\InterventionHasDateRepository")
 */

class InterventionHasDate
{
    /**
     *@Assert\Date
     * @var string A "Y-m-d" formatted value
     *@ORM\Id
     * @ORM\Column(name="dateIntervention", type="string", nullable=false, options={"default"="0000-00-00"})
     * 
     */
    private $dateintervention = '0000-00-00';
     /**
     * @var \Intervention
     *@ORM\Id
     * @ORM\ManyToOne(targetEntity="Intervention", inversedBy="dates")
     * 
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="intervention_idIntervention", referencedColumnName="idIntervention")
     * })
     */
    private $interventionIdintervention;

    /**
     * @var \Time
     *
     * @ORM\Column(name="HeureDebut", type="time", nullable=false)
     */
    private $heuredebut;

    /**
     * @var \Time
     *
     * @ORM\Column(name="HeureFin", type="time", nullable=false)
     */
    private $heurefin;

   /**
 * @return \DateTime
 */

    public function getDateintervention()
    {

        return \DateTime::createFromFormat('Y-m-d|', $this->dateintervention);
    }


    public function getHeuredebut(): ?\DateTimeInterface
    {
        return $this->heuredebut;
    }

    public function setHeuredebut(\DateTimeInterface $heuredebut): self
    {
        $this->heuredebut = $heuredebut;

        return $this;
    }

    public function getHeurefin(): ?\DateTimeInterface
    {
        return $this->heurefin;
    }

    public function setHeurefin(\DateTimeInterface $heurefin): self
    {
        $this->heurefin = $heurefin;

        return $this;
    }

    public function getInterventionIdintervention(): ?Intervention
    {
        return $this->interventionIdintervention;
    }

    public function setInterventionIdintervention(?Intervention $interventionIdintervention): self
    {
        $this->interventionIdintervention = $interventionIdintervention;

        return $this;
    }



    /**
     * Set dateintervention.
     *
     * @param \DateTime $dateintervention
     *
     * @return InterventionHasDate
     */
    public function setDateintervention($dateintervention)
    {
        $this->dateintervention = $dateintervention->format('Y-m-d');

        return $this;
    }

}

实体干预:

/**
 * Intervention
 *
 * @ORM\Table(name="intervention", uniqueConstraints={@ORM\UniqueConstraint(name="idIntervention", columns={"idIntervention"})}, indexes={@ORM\Index(name="contact_rdv_2", columns={"contact_rdv"}), @ORM\Index(name="contact_confirmation", columns={"contact_confirmation"}), @ORM\Index(name="idUser", columns={"idUser"}), @ORM\Index(name="contact_correspondant", columns={"contact_correspondant"}), @ORM\Index(name="nomStatut", columns={"nomStatut"})})
 * @ORM\Entity(repositoryClass="ssi\planificationBundle\Repository\InterventionRepository")
 */
class Intervention
{
    /**
     * @var int
     *
     * @ORM\Column(name="idIntervention", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $idintervention;
     .....


    /**
     * @var \Doctrine\Common\Collections\Collection
     *@ORM\OneToMany(targetEntity="InterventionHasDate", mappedBy="interventionIdintervention")
     */
    private $dates;



    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="User", inversedBy="interventionIdintervention")
     * @ORM\JoinTable(name="intervention_has_user",
     *   joinColumns={
     *     @ORM\JoinColumn(name="intervention_idIntervention", referencedColumnName="idIntervention")
     *   },
     *   inverseJoinColumns={
     *     @ORM\JoinColumn(name="user_idUser", referencedColumnName="idUser")
     *   }
     * )
     */
    private $userIduser;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="Visite", mappedBy="interventionIdintervention")
     */
    private $visiteIdvisite;

    /**
     * @return Collection|InterventionHasDate[]
     */
    public function getDates(): Collection
    {
        return $this->dates;
    }

    public function addDates(InterventionHasDate $dates): self
    {
        if (!$this->dates->contains($dates)) {
            $this->dates[] = $dates;
            $dates->addDates($this);
        }

        return $this;
    }

    public function removeDates(InterventionHasDate $dates): self
    {
        if ($this->dates->contains($dates)) {
            $this->dates->removeElement($dates);
            $dates->removeDates($this);
        }

        return $this;
    }


    /**
     * @return Collection|User[]
     */
    public function getUserIduser(): Collection
    {
        return $this->userIduser;
    }

    public function addUserIduser(User $userIduser): self
    {
        if (!$this->userIduser->contains($userIduser)) {
            $this->userIduser[] = $userIduser;
            $userIduser->addInterventionIdintervention($this);
        }

        return $this;
    }

    public function removeUserIduser(User $userIduser): self
    {
        if ($this->userIduser->contains($userIduser)) {
            $this->userIduser->removeElement($userIduser);
            $userIduser->removeInterventionIdintervention($this);
        }

        return $this;
    }


    public function __construct()
    {
        $this->installationIdinstallation = new \Doctrine\Common\Collections\ArrayCollection();
        $this->userIduser = new \Doctrine\Common\Collections\ArrayCollection();
        $this->visiteIdvisite = new \Doctrine\Common\Collections\ArrayCollection();
        $this->dates=new \Doctrine\Common\Collections\ArrayCollection();
    }

我的 html/twig :

{% extends 'planification/base.html.twig' %}
{% block title %}
Home
{% endblock %}
{% block body %}
 <div id="corps">

        <h1>Intervention</h1>
        <h3>{{ form_start(form)}}</h3>
        {{ form_errors(form)}}

        <div class="block-position">
        {{ form_errors(form.idtypeinter) }}
        <h3>{{ form_label(form.idtypeinter)}}{{ form_widget(form.idtypeinter)}}{{ form_widget(form.Valider) }}</h3>
        </div>

        {% if form.idtypeinter.vars.value == "Dépannage" 
        or form.idtypeinter.vars.value == "Mise en service" 
        or form.idtypeinter.vars.value == "Travaux" 
        or form.idtypeinter.vars.value == "Vérification" %}
    <div class="block-position">

            {{ form_errors(form.site) }}
            <h3>{{ form_label(form.site) }}{{ form_widget(form.site) }}{{ form_widget(form.Validersite) }}</h3>
            {{ form_errors(form.batiment) }}
            <h3>{{ form_label(form.batiment) }}{{ form_widget(form.batiment) }}{{ form_widget(form.Validerbatiment) }}</h3>

            {% if form.idtypeinter.vars.value != "Vérification" %}
                <h3>{{ form_errors(form.installationIdinstallation) }}{{ form_label(form.installationIdinstallation) }}</h3>
                {% if form.batiment.vars.value != NULL %}
                    {% for installation in form.installationIdinstallation %}
                        <h4>{{ form_widget(installation) }}{{ form_label(installation) }}</h4>
                    {% endfor %}
                    <h3>{{ form_row(form.AfficherplusInstallations) }}</h3>
                {% endif %}
            {% else %}
                <h3>{{ form_errors(form.visiteIdvisite) }}{{ form_label(form.visiteIdvisite) }}</h3>
                {% if form.batiment.vars.value != NULL %}
                    {% for visite in form.visiteIdvisite %}
                        <h4>{{ form_widget(visite) }}{{ form_label(visite) }}</h4>
                    {% endfor %}
                    <h3>{{ form_row(form.AfficherplusVisites) }}</h3>
                {% endif %}
            {% endif %}
            </div>
        <div class="block-position">
        {{ form_errors(form.numerointervention) }}
        <h3>{{ form_row(form.numerointervention) }}</h3>
        {{ form_errors(form.contactCorrespondant) }}
        <h3>{{ form_row(form.contactCorrespondant) }}</h3>
        {{ form_errors(form.contactRdv) }}
        <h3>{{ form_row(form.contactRdv) }}</h3>
        {{ form_errors(form.contactConfirmation) }}
        <h3>{{ form_row(form.contactConfirmation) }}</h3>
        </div>
        {% endif %}
        <div class="block-position">
        {{ form_errors(form.dates) }}
        <h3>{{ form_label(form.dates) }}
        <ul id="dates-fields-list" 
        data-prototype="{{form_widget(form.dates.vars.prototype) |e('html_attr')}}"
        data-widget-tags="{{ '<li></li>'|e }}"
        data-widget-counter="{{ form.dates|length }}">
            {% for datesField in form.dates %}
                <li id="{{ "list_" ~ datesField.vars.id }}">
                    {{ form_widget(datesField.dateintervention)}}
                    {% if form.idtypeinter.vars.value != "Astreinte" %}
                    {{form_widget(datesField.heuredebut ) }}

                    {{form_widget(datesField.heurefin  )}}
                    {% endif %}
                    <button  type="button" class="remove-another-collection-widget" onclick="deleteLink( {{ "list_" ~ datesField.vars.id }})">Retirer</button>

                </li>

        {% endfor %}

        </ul><button type="button" class="add-another-collection-widget" data-list-selector="#dates-fields-list">Ajouter</button></h3>
        </div>
        <div class="block-position">
        {{ form_errors(form.iduser) }}
        <h3>{{ form_row(form.iduser) }}</h3>
        {{ form_errors(form.commentaire) }}
        <h3>{{ form_row(form.commentaire) }}</h3>
        {{ form_errors(form.nomstatut) }}
        <h3>{{ form_row(form.nomstatut) }}</h3>
        </div>
        <div class="block-position">
        {{ form_errors(form.userIduser) }}
        <h3>{{ form_label(form.userIduser) }}

        <ul id="technicien-fields-list" data-prototype="{{ form_widget(form.userIduser.vars.prototype)|e('html_attr') }}"
        data-widget-tags="{{ '<li></li>'|e }}"
        data-widget-counter="{{ form.userIduser|length }}">
            {% for technicienField in form.userIduser %}
                <li id="{{ "list_" ~ technicienField.vars.id }}">
                    {{ form_errors(technicienField) }}
                    {{ form_widget(technicienField) }} <button  type="button" class="remove-another-collection-widget" onclick="deleteLink( {{ "list_" ~ technicienField.vars.id }})">Retirer</button>

                </li>

        {% endfor %}
        </ul> <button type="button" class="add-another-collection-widget" data-list-selector="#technicien-fields-list">Ajouter</button>
        </h3>
        <button type="submit">Essayer</button>
        </div>
        <h3>{{ form_row(form.Enregistrer) }}</h3>
        {{ form_row(form._token) }}
        {{ form_end(form, {'render_rest': false})}} 
</div>
{% endblock %}

剧本:

jQuery(document).ready(function () {

    jQuery('.add-another-collection-widget').click(function (e) {
        var list = jQuery(jQuery(this).attr('data-list-selector'));
        // Try to find the counter of the list or use the length of the list
        var counter = list.data('widget-counter') || list.children().length;

        // grab the prototype template
        var newWidget = list.attr('data-prototype');
        // replace the "__name__" used in the id and name of the prototype
        // with a number that's unique to your emails
        // end name attribute looks like name="contact[emails][2]"
        newWidget = newWidget.replace(/__name__/g, counter);
        // Increase the counter
        counter++;
        // And store it, the length cannot be used if deleting widgets is allowed
        list.data('widget-counter', counter);

        // create a new list element and add it to the list
        var newElem = jQuery(list.attr('data-widget-tags')).html(newWidget);
        addTagFormDeleteLink(newElem);
        newElem.appendTo(list);
    });
    function addTagFormDeleteLink($tagFormLi) {
        var $removeFormButton = $(' <button type="button"> Retirer</button>');
        $tagFormLi.append($removeFormButton);

        $removeFormButton.on('click', function(e) {
            // remove the li for the contact form
            $tagFormLi.remove();
        });
    }
});
function deleteLink(id){
    id.remove();
}

该脚本适用于我网站的其他页面。 我已经有几天遇到麻烦了...如果有人能帮助我,我将不胜感激。

更新 有时我设法理解我的脚本破坏了我的 collection。 我找到的唯一解决方案是停止使用它并手动添加行。

新密码:

<h3>{{ form_label(form.dates) }}
        <ul>

            {% for datesField in form.dates %}

                <li id="{{ "list_" ~ datesField.vars.id }}">
                    {{ form_widget(datesField.dateintervention)}}
                    {% if form.idtypeinter.vars.value != "Astreinte" %}
                    {{form_widget(datesField.heuredebut ) }}

                    {{form_widget(datesField.heurefin  )}}
                    {% endif %}
                    <button  type="button" class="remove-another-collection-widget" onclick="deleteLink( {{ "list_" ~ datesField.vars.id }})">Retirer</button>
                </li>
            {% endfor %}
            {% if form.Ajouterdate.vars.clicked ==1 %}
               {% set number = form.dates|length %}
               <li id="{{ "list_ssi_planificationbundle_intervention_dates_" ~ number  }}">
               <input type="date" id="ssi_planificationbundle_intervention_dates_{{number}}_dateintervention" name="ssi_planificationbundle_intervention[dates][{{number}}][dateintervention]" required="required" >
               <input type="time" id="ssi_planificationbundle_intervention_dates_{{number}}_heuredebut" name="ssi_planificationbundle_intervention[dates][{{number}}][heuredebut]" required="required" step="900">
              <input type="time" id="ssi_planificationbundle_intervention_dates_{{number}}_heurefin" name="ssi_planificationbundle_intervention[dates][{{number}}][heurefin]" required="required" step="900">
               <button  type="button" class="remove-another-collection-widget" onclick="deleteLink( {{ "list_ssi_planificationbundle_intervention_dates_" ~ number  }})">Retirer</button>
           </li>
        {% endif %}
    </ul>{{form_row(form.Ajouterdate)}}
</h3>
</div>

它有效,但不是最佳解决方案。有人有更好的主意吗?