如何使用数据原型symfony 2.8创建3个级别的表单

时间:2017-05-05 09:47:05

标签: forms symfony symfony-2.8

我有3个人:(简历,DomaineCompetence和Competences) CV可以有很多DomaineCompetence,而DomaineCompetence可以有很多Competences,每个实体都有一个formType。

Cv实体

class Cv
{ 
 //...

  /**
   * @OneToMany(targetEntity="DomaineCompetenceCv", mappedBy="cv", cascade={"persist"})
   * 
   */
   private $domainesCompetence;

DomaineCompetence Entity

class DomaineCompetenceCv
{
 /**
  * @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)
 */
private $nom;

/**
 * @ORM\ManyToOne(targetEntity="Cv", inversedBy="domainesCompetence")
 * @ORM\JoinColumn(name="cv_id", referencedColumnName="id")
 */
private $cv;

/**
 * @ORM\OneToMany(targetEntity="CompetenceCv", mappedBy="domaineCompetence", cascade={"persist"})
 * 
 */
private $competences;

CompetenceCv

class CompetenceCv
{
/**
 * @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)
 */
private $nom;

/**
 * @ORM\Column(name="niveau", type="integer")
 */
private $niveau;

/**
 * @ORM\ManyToOne(targetEntity="DomaineCompetenceCv", inversedBy="competences")
 * @ORM\JoinColumn(name="domaine_id", referencedColumnName="id")
 */
private $domaineCompetence;

CVForm

 public function buildForm(FormBuilderInterface $builder, array $options)
{ $builder
    //...
    ->add('domainesCompetence', CollectionType::class, array(

        'entry_type' => DomaineCompetenceCvForm::class,
        'allow_add'    => true,
        'by_reference' => false,


    ))      
        ;

}

DomaineCompetenceCvForm

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('nom')
            ->add('competences', CollectionType::class, array(

        'entry_type' => CompetenceCvForm::class,
        'allow_add'    => true,
        'by_reference' => true,


    ))      
            ;
}

CompetencesCvForm

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

Cv的Twig

 <form role="form" action="" {{ form_enctype(form) }} method="POST">
                             {{ form_widget(form._token) }}  
    //...
     <h4 class="no-margin-top has-divider text-highlight">Compétences</h4>
             <div id="domaineCV" class="domaineCV" data-prototype="{{ form_widget(form.domainesCompetence.vars.prototype)|e('html_attr') }}">

                 {% for com in form.domainesCompetence %}

                   <div class="" data-prototype="{{ form_widget(com.vars.prototype)|e('html_attr') }}">

                   </div>
                   {% endfor %}
               </div>
   </form>     

我使用javaScript添加超过DomaineCompetence但问题是没有显示Competence的形式

有人可以帮我吗?谢谢大家。

twig render JS for domainesCompetence

<script type="text/javascript">
 $(document).ready(function() {

var $container = $('div#domaineCV');


var $addLink = $('<a href="#" id="add_category" class="btn btn-default">Ajouter une Domaine de compétence</a>');
$container.append($addLink);


$addLink.click(function(e) {
  addCategory($container);
  e.preventDefault(); // évite qu'un # apparaisse dans l'URL
  return false;
});


var index = $container.find(':input').length;


if (index == 0) {
  addCategory($container);
} else {

  $container.children('div').each(function() {
    addDeleteLink($(this));
  });
}


function addCategory($container) {

  var $prototype = $($container.attr('data-prototype').replace(/__name__label__/g, 'Catégorie n°' + (index+1))
      .replace(/__name__/g, index));


  addDeleteLink($prototype);


  $container.append($prototype);

  index++;
}


function addDeleteLink($prototype) {

  $deleteLink = $('<a href="#" class="btn btn-danger">Supprimer</a>');


  $prototype.append($deleteLink);


  $deleteLink.click(function(e) {
    $prototype.remove();
    e.preventDefault(); =
    return false;
  });
}

});

1 个答案:

答案 0 :(得分:2)

我在我的本地环境中重现了你的问题,同样的堆栈(Symfony 2.8.20)

从截图中我可以看到DomainesCompetence表单显示在Cv表单中,因为您创建了用于处理此集合的js。但是你确定实际的js处理每个 DomaineCompetence 表单中的能力集合吗?

也许你需要customize your CompetenceCvType collection prototype。请提供反馈。

**编辑:脏解决方案(工作但需要重构!!!)**

首先,在渲染Cv表单模板时填充DomaineCompetence(嵌入在Cv表单中)表单原型,但是未在DomaineCompetence表单中填充嵌入的Competence表单原型。您可以在控制器中填充二级表单集合,如下所示:

<?php

namespace AppBundle\Controller;

use AppBundle\Form\CvType;
use AppBundle\Form\DomaineCompetenceCvType;
use AppBundle\Form\CompetenceCvType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class CvController extends Controller
{
    /**
     * @Route("/new")
     */
     public function newAction()
     {
         $form = $this->createForm(CvType::class);
         $domaineCompetenceCvForm = $this
             ->createForm(
                 CompetenceCvType::class,
                 null,
                 array('auto_initialize' => false
             )
         );
         $form->get('domainesCompetence')
             ->add($domaineCompetenceCvForm)
         ;


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

接下来更新你的模板:

{% extends 'base.html.twig' %}

{% form_theme form _self %}

{% block _appbundle_cv_domainesCompetence_entry_widget %}
    {{ form_row(form.nom) }}
{% endblock %}

{% block title %}AppBundle:Cv:new{% endblock %}

{% block body %}
    <h1>Welcome to the Cv:new page</h1>

    <form role="form" action="" {{ form_enctype(form) }} method="POST">
        {{ form_widget(form._token) }}  

        <h4 class="no-margin-top has-divider text-highlight">Compétences</h4>
        Domaines
        <div style="border: 1px solid green" id="domaineCV" class="domaineCVs" data-prototype="{{ form_widget(form.domainesCompetence.vars.prototype)|e('html_attr') }}">

            <div style="border: 1px solid yellow" id="competencesProto" data-prototype="{{ form_widget(form.children.domainesCompetence)|e('html_attr') }}">
            </div>
        </div>


    </form> 
{% endblock %}
{% block javascripts %}
    {{ parent() }} {# load your jquery and bootstrap deps #}
    <script type="text/javascript">
        {# custom js handling your collections here #}
    </script>

{% endblock %}

然后这是js:

$(document).ready(function() {

    var $prototype = '';
    var $container = $('div#domaineCV');
    var $competencesContainer = '';
    var $competencesProtoContainer = $('div#competencesProto');

    var $addLink = $('<a href="#" id="add_category" class="btn btn-success">Ajouter une Catégorie</a>');
    var $addCompetence = $('<a href="#" id="add_competence" class="btn btn-warning">Ajouter une compétence</a>');
    $container.after($addLink);


    $addLink.click(function(e) {
        addCategory($container);
        e.preventDefault(); // évite qu'un # apparaisse dans l'URL
        return false;
    });

    $addCompetence.click(function(e) {
        addCompetence($competencesContainer);
        e.preventDefault(); // évite qu'un # apparaisse dans l'URL
        return false;
    });


    var index = $container.find(':input').length;
    var competencesIndex = 0;

    if (index == 0) {
        addCategory($container);
        competencesIndex = $competencesContainer.find(':input').length; 
    } else {
        $container.children('div').each(function() {
          addDeleteLink($(this));
        });
    }

    function addCategory($container) {

        $prototype = $($container.attr('data-prototype').replace(/__name__label__/g, 'Catégorie n°' + (index+1))
            .replace(/__name__/g, index));
        $container.prepend($prototype);
         $competencesContainer = $('div#competencesProto');
        $competencesContainer.after($addCompetence);   

        addCompetence($competencesContainer);

        addDeleteLink($prototype);

        index++;
    }

    function addCompetence($competencesContainer) {
        var $competenceProto = $($competencesProtoContainer.attr('data-prototype').replace(/__name__label__/g, 'Catégorie n°' + (competencesIndex+1))
          .replace(/__name__/g, competencesIndex));

      $competencesContainer.append($competenceProto);
      $prototype.append($competenceProto);
  
      addCompetenceDeleteLink($competenceProto);

      competencesIndex++;
    }

    function addDeleteLink($element) {
        $deleteLink = $('<a href="#" class="btn btn-danger">Supprimer catégorie</a>');

        $element.append($deleteLink);


        $deleteLink.click(function(e) {
            $element.remove();
            e.preventDefault(); 
            return false;
        });
    }

    function addCompetenceDeleteLink($element) {

        $deleteCompetenceLink = $('<a href="#" class="btn btn-danger">Supprimer competence</a>');

        $element.append($deleteCompetenceLink);


        $deleteCompetenceLink.click(function(e) {
          $element.remove();
          e.preventDefault(); 
          return false;
        });
    }

});