Symfony动态表单提交的表单

时间:2017-06-25 00:02:26

标签: javascript php jquery ajax symfony

我正在关注http://symfony.com/doc/current/form/dynamic_form_modification.html#dynamic-generation-for-submitted-forms

上的教程

这个想法是我得到了3级Animal => Spieces =>种族 在创造一种新动物的过程中,我想根据Spieces动态改变种族的选择。

以下是我的课程:种族

class Race
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @ORM\ManyToOne(targetEntity="Rendy\AppBundle\Entity\Espece", inversedBy="race")
     * @ORM\JoinColumn(name="espece_id", referencedColumnName="id", onDelete="CASCADE", nullable=false)
     */
    private $espece;

类动物

class Animal
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @var Espece
     *
     *
     * @ORM\ManyToOne(targetEntity="Espece")
     * @ORM\JoinColumn(name="espece_id", referencedColumnName="id", onDelete="CASCADE")
     */
    private $espece;

    /**
     * @var string
     *
     * @ORM\ManyToOne(targetEntity="Race")
     * @ORM\JoinColumn(name="race_id", referencedColumnName="id", onDelete="CASCADE")
     */
    private $race;

班级Spieces:

class Espece
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var string
     *
     * @ORM\Column(name="nom", type="string", length=255, unique=true)
     */
    private $nom;


    /**
     * @ORM\OneToMany(targetEntity="Race", mappedBy="espece")
     * @ORM\JoinColumn(name="race_id", referencedColumnName="id")
     */
    private $race;

   /**
     * Get race
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getRace()
    {
        return $this->race;
    }

这是我的控制器

public function newAction(Request $request)
    {
        $animal = new Animal();

        $form = $this->createForm(AnimalType::class, $animal);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
          // do something after
                      }

        return $this->render('RendyAppBundle:animal:new.html.twig', array(
            'form' => $form->createView(),
        ));
    }

这是我的AnimalType表格

class AnimalType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('nom');


        $builder->add('espece', EntityType::class, array(
            'class'         => 'RendyAppBundle:Espece',
            'choice_label'  => 'nom',
            'placeholder'   => '',
            ));

        $formModifier = function (FormInterface $form, Espece $espece = null) {
            $race = null === $espece ? array() : $espece->getRace();

            $form->add('race', EntityType::class, array(
                'class'         => 'RendyAppBundle:Race',
                'choice_label'  => 'nom',
                'placeholder'   => '',
                'choices'       => $race,
            ));
        };
        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($formModifier) {

                $data = $event->getData();
                $formModifier($event->getForm(), $data->getEspece());
            }
        );

        $builder->get('espece')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use ($formModifier) {
                $espece = $event->getForm()->getData();
                $formModifier($event->getForm()->getParent(), $espece);
            }
        );

结束观点!

{% block body%}

    {{ form_start(form) }}
        {# render the task's only field: description #}
        {{ form_row(form.nom) }}
        {{ form_row(form.espece, {'id': 'test','attr': {'onChange': 'changed()'}}) }}
        {{ form_row(form.race, {'id': 'animal_race', 'attr': { 'class': 'form-control'}}) }}
        {{ form_row(form.sexe) }}
        {{ form_row(form.age) }}

        {{ form_row(form.puce) }}
        {{ form_row(form.poids) }}

        <h3>Comportement</h3>
        <ul class="comportement">
            {# iterate over each existing tag and render its only field: name #}
            {% for comportement in form.comportement %}
                <li>{{ form_row(comportement.name) }}</li>
            {% endfor %}
        </ul>
    {{ form_end(form) }}



{% endblock %}

{% block ajax %}
<script>

function changed() {
    var espece = $('#test');
    // ... retrieve the corresponding form.
    var $form = $('#form');

    console.log($form);
    // Simulate form data, but only include the selected sport value.
    var data = {};
    data[espece.attr('nom')] = espece.val();
    // Submit data via AJAX to the form's action path.
    jQuery.ajax({
        url : $form.attr('action'),
        type: "POST",
        data: data,
        success: function (html) {
            console.log(html)
            $("#animal_race").replaceWith(
                // ... with the returned one from the AJAX response.
                $(html).find("#animal_race")
            );
            // Position field now displays the appropriate positions.
        }
    });
}
</script>
{% endblock %}

当我更改“Especes”的值时调用Ajax函数,但是我的字段Race仍然是空白的...(我的块ajax在块javascripts之后)

Ajax请求: POST参数 核心价值 undefined“2”

当我做一个简单的Animal-&gt; getEspece() - &gt; getRace();我得到了一个包含良好信息的数组。

我用Google搜索,尝试,谷歌搜索,我想我错过了什么。

感谢您的帮助

2 个答案:

答案 0 :(得分:0)

您正在将请求(在AJAX调用中)发送到与加载页面相同的URL(表单操作URL)(newAction&#39; s请求)。如果你的newAction方法实际上将数据发送到传入的POST / GET请求,这可能会有效,但这不是这里的情况。

我建议始终专门为POST请求创建一个单独的路由(因此单独的控制器方法)。您也无法发送数据(当您从数据库中检索时,该数据位于对象中)&#39;按原样排列。您将不得不将其转换为例如JSON。您可以将整个对象直接转换为JSON(https://symfony.com/doc/current/components/serializer.html),但最好只获取所需的信息。为此,您可以创建一个包含此信息的数组

总而言之,您的控制器方法看起来像这样:

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

public function getRacesJsonAction(Request $request)
{
    //Get the race data here that you want to send (edit to your own needs)
    $race = $Animal->getEspece()->getRace();

    //Convert the entity directly to a JSON
    $jsonContent = $serializer->serialize($race, 'json');

    //create a response 
    $response = new Response($jsonContent);
    $response->headers->set('Content-Type', 'application/json');

    return $response;
}

在你的前端,你必须将json解码为javascript数组,如下所示:

  $.ajax({
      type: 'POST',
      url: url,
      data: {
          data: dataObj
      },
      dataType: 'json',
      success: function(data) {
        console.log('success');
        //Obj is the array with information now
        obj = JSON.parse(json);
      },
      error: function(data) {
        console.log('fail');
      }
  });

但是,您无法直接填充obj-array中的此信息。您将不得不解析它,因为HTML下拉列表中的每个条目都包含如下:

<ul>
</li>race1</li>
</li>race2</li>
</li>race3</li>
</ul>

它的广泛实施。我可能在语法上犯了错误,所以要小心。我还建议您使用&#39; FOSJsRoutingBundle&#39;,它允许您从javascript中的路线创建URL。您可能会将路径的路径转换为保存网址的javascript变量。

祝你好运!

答案 1 :(得分:0)

这是我正在运作的代码

控制器:

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

use AppBundle\Entity\Animal;
use AppBundle\Form\Type\AnimalType;
// ...

class MeetupController extends Controller
{
    /**
     * @Route("/animal")
     */
    public function animalAction(Request $request)
    {
        $meetup = new Animal();
        $form = $this->createForm(AnimalType::class, $meetup);
        $form->handleRequest($request);
        if ($form->isValid()) {
            // ... save the meetup, redirect etc.
        }

        return $this->render(
            ':Meetup:animal.html.twig',
            array('form' => $form->createView())
        );
    }

    // ...
}

animal.html.twig

{% block body %}
{{ form_start(form) }}

   {{ form_row(form.espece) }}
   {{ form_row(form.race) }}
    {# ... #}
{{ form_end(form) }}

<script   src="https://code.jquery.com/jquery-2.2.4.min.js"   integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="   crossorigin="anonymous"></script>
<script>
    var $espece = $('#animal_espece');
    // When especegets selected ...
    $espece.change(function() {
        console.log("Dans la fonction Change");
        // ... retrieve the corresponding form.
        var $form = $(this).closest('form');
        // Simulate form data, but only include the selected espece value.
        var data = {};
        data[$espece.attr('name')] = $espece.val();

        // Submit data via AJAX to the form's action path.
        $.ajax({
            url : $form.attr('action'),
            type: $form.attr('method'),
            data : data,
            success: function(html) {
                // Replace current race field ...
                $('#animal_race').replaceWith(
                        // ... with the returned one from the AJAX response.
                        $(html).find('#animal_race')
                );
                // race field now displays the appropriate positions.
            }
        });
    });
</script>
{% endblock %}

AnimalType

<?php

namespace AppBundle\Form\Type;

use AppBundle\Entity\Espece;
use AppBundle\Entity\Animal;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormInterface;

// ...

class AnimalType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('espece', EntityType::class, array(
                'class'       => 'AppBundle:Espece',
                'placeholder' => '',
            ))
        ;

        $formModifier = function (FormInterface $form, Espece $sport = null) {
            $positions = null === $sport ? array() : $sport->getAvailablePositions();

            $form->add('race', EntityType::class, array(
                'class'       => 'AppBundle:Race',
                'placeholder' => '',
                'choices'     => $positions,
            ));
        };

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

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

        $builder->get('espece')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use ($formModifier) {
                $sport = $event->getForm()->getData();
                $formModifier($event->getForm()->getParent(), $sport);
            }
        );
    }

}

Espece实体

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

/**
 * Espece
 *
 * @ORM\Table(name="espece")
* @ORM\Entity(repositoryClass="AppBundle\Repository\EspeceRepository")
 */
class Espece
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var string
     *
     * @ORM\Column(name="nom", type="string", length=255, unique=true)
     */
    private $nom;

   /**
    * @var Collection|Race[]
    *
    * @ORM\OneToMany(targetEntity="Race", mappedBy="espece")
    */
   protected $racesdisponibles;


    public function __constructor()
    {
        $this->racesdisponibles = new ArrayCollection();
    }

    public function __toString()
    {
        return $this->nom;
    }

和种族实体

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Race
 *
 * @ORM\Table(name="race")
  * @ORM\Entity(repositoryClass="AppBundle\Repository\RaceRepository")
 */
class Race
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @var Espece
     * @ORM\ManyToOne(targetEntity="Espece", inversedBy="racesdisponibles")
     * @ORM\JoinColumn(name="espece_id", referencedColumnName="id", onDelete="CASCADE", nullable=false)
     */
    private $espece;

    public function __toString()
    {
        return $this->nom;
    }

如果需要给我发消息,我会发给你捆绑:) 我的错误就在这里

data[espece.attr('nom')] = espece.val();

关于DOM,好的anwser是

data[espece.attr('name')] = espece.val();

我认为&#34;名字&#34;是运动实体的属性,而<div name="beeeeer">

是属性

希望能帮到某人