Génération des fields dynamiquement selon une requete

Default
,

Bonjour tout le monde,

Je galère depuis plus qu'une semaine pour créer un formulaire avec des fields qui varient en fonction d'une requête sql sous symfony2.2

ci dessous mes entités Critere, TypeVote et mon controlleur , le but consiste à exécuter une requête de jointure entre Critère et TypeVote pour retourner la liste de critère d'un type de vote bien déterminé et selon ce retour générer un formulaire de vote avec des case à cocher.

comment je peux faire ca avec VoteRepository et générer ma form dynamiquement aidez moi svp?

/////////////////////////////Entity TypeVote/////////////////////////////////////////////
class TypeVote {


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


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


   /**
   * @ORM\ManyToOne(targetEntity="My\VoteBundle\Entity\TypeVote", cascade={"persist"})
   * @ORM\JoinColumn(name="TypeVote_id",nullable=false)
   */




    private $typeVote;
  /**
   * @var string $nom
   *
   * @ORM\Column(name="nom", type="string", length=255)
   */
  private $nom;
}
///////////////////////////////////Controlleur///////////////////////////////////
public function voteAction(Request $request, Entreprise $entreprise) {
        // $test = 2 ; ladybug_dump($test); exit; 
        ini_set('display_errors', '1'); 
        $voteId=12;//on suppose que le type de vote a comme id 12
        $em = $this->container->get('doctrine')->getManager();
        $user = $this->container->get('security.context')->getToken()->getUser();
        $note = 0;
        //echo get_class($user);
        /* if (!is_object($user) || !$user instanceof UserInterface) {
          throw new AccessDeniedException('This user does not have access to this section.');
          } */
        $vote = new Vote();
        $vote
                ->setDateVote(new \DateTime())
                ->setUser($user)
                ->setEntreprise($entreprise);




        $form = $this->container->get('form.factory')->create(new VoterForm(), $vote);
        if ($request->getMethod() == 'POST') {
            $form->bindRequest($request);
            if ($form->isValid()) {


                $typeVote = $this->getDoctrine() ->getRepository('MyVoteBundle:TypeVote')->find($voteId);   
                $vote->setTypeVote($typeVote);


                $note=20;
                $vote->setNote($note);
                $em->persist($vote);
                $em->flush();
                return $this->redirect($this->generateUrl('my_vote_liste'));
            }
        }
        return $this->container->get('templating')->renderResponse('MyVoteBundle:SearchEntreprise:vote.html.twig', array(
                    'entreprise' => $entreprise,
                    'form' => $form->createView())
        );
    }

6 Réponse

581
,

Salut,

il nous faudrait ton fichier VoterForm pour pouvoir t'aider pour le coup. C'est lui qui doit construire le formulaire dynamiquement a priori, non ?

En tous cas, ça me semble faisable, il faudrait "simplement" ajouter les champs en fonction des paramètres du constructeur par exemple.

Default
,

Merci pour votre réponse Alex-D, voila mon VoterForm j'espère que c'est claire:

class VoterForm extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options) {
        // $qb = $em->createQueryBuilder();
        $builder->add('critere', 'entity', array(
            'class' => 'MyVoteBundle:Vote',
            // 'property' => 'titre',
            'property' => 'critere',
            'query_builder' => function(VoteRepository $v) {
                return $v->getCritereVote();
               // ladybug_dump($v);
                foreach ($nom as $v) {
                    $builder->add($nom, 'choice', array(
                        'choices' => array('pas_bien' => 'Pas bien', 'acceptable' => 'Acceptable', 'bon' => 'Bon', 'tres_bon' => 'Très Bon', 'excellent' => 'Excellent'),
                        'expanded' => true,
                        'multiple' => false
                    ));
                }
               // $builder->add('save', 'submit')
                      // ->getForm();
            }
        ));


    }
    public function getName() {
        return 'critere';
    }


}

Mon getCritereVote est là:

public function getCritereVote() {




        $qb = $this->createQueryBuilder('a');
        $qb->select('a.nom')
                ->leftJoin('a.typevote', 't')
                ->where('t.typeVote_id = 13') // j'ai pris l'exemple de 13 pour typeVote_id 
                 ->distinct('a.id');
        return $qb->getQuery();
                      // ->getResult();


      }
Default
,

Bonjour,

Si j'ai bien compris votre probleme, je pense que ce lien repondra à votre question : Openclassroom

Il suffit tout simplement d'adapter le script à votre VoterForm.php !!

<script type="text/javascript">
$(document).ready(function() {
  // On récupère la balise <div> en question qui contient l'attribut « data-prototype » qui nous intéresse.
  var $container = $('div#myvotebundle_voteform_typevote');
  // On ajoute un lien pour ajouter une nouvelle catégorie
  var $lienAjout = $('<a href="#" id="ajout_categorie" class="btn">Ajouter une catégorie</a>');
  $container.append($lienAjout);
  // On ajoute un nouveau champ à chaque clic sur le lien d'ajout.
  $lienAjout.click(function(e) {
    ajouterCategorie($container);
    e.preventDefault(); // évite qu'un # apparaisse dans l'URL
    return false;
  });
  // On définit un compteur unique pour nommer les champs qu'on va ajouter dynamiquement
  var index = $container.find(':input').length;
  // On ajoute un premier champ directement s'il n'en existe pas déjà un (cas d'un nouvel article par exemple).
  if (index == 0) {
    ajouterCategorie($container);
  } else {
    // Pour chaque catégorie déjà existante, on ajoute un lien de suppression
    $container.children('div').each(function() {
      ajouterLienSuppression($(this));
    });
  }
  // La fonction qui ajoute un formulaire Categorie
  function ajouterCategorie($container) {
    // Dans le contenu de l'attribut « data-prototype », on remplace :
    // - le texte " __name__ label__" qu'il contient par le label du champ
    // - le texte " __name__" qu'il contient par le numéro du champ
    var $prototype = $($container.attr('data-prototype').replace(/ __name__ label__/g, 'Catégorie n°' + (index+1))
                                                        .replace(/ __name__ /g, index));
    // On ajoute au prototype un lien pour pouvoir supprimer la catégorie
    ajouterLienSuppression($prototype);
    // On ajoute le prototype modifié à la fin de la balise <div>
    $container.append($prototype);
    // Enfin, on incrémente le compteur pour que le prochain ajout se fasse avec un autre numéro
    index++;
  }
  // La fonction qui ajoute un lien de suppression d'une catégorie
  function ajouterLienSuppression($prototype) {
    // Création du lien
    $lienSuppression = $('<a href="#" class="btn btn-danger">Supprimer</a>');
    // Ajout du lien
    $prototype.append($lienSuppression);
    // Ajout du listener sur le clic du lien
    $lienSuppression.click(function(e) {
      $prototype.remove();
      e.preventDefault(); // évite qu'un # apparaisse dans l'URL
      return false;
    });
  }
});
</script>
Default
,

Bonjour hbenyoussef,

Merci pour votre réponse sauf que ce code ne répond pas à mon besoin, je vous explique, j'ai besoin de générer un formulaire de vote constitué d'un ensemble de cases à cocher , ces attributs sont variables, ils varient du retour d'une requête, donc j'aurai besoin de faire une boucle sur le retour de la raquette qui est dans mon repository dans ma form et de générer des cases a cocher c'est là ou je me bloque.

581
,

Pour moi, ça se passe au niveau du formbuilder.

J'ai déjà eu à faire ce genre de manipulation, mais personnellement j'ai fait tout ça à l'arrache à la main ^^"

Mais je pense qu'il faut utiliser un formbuilder qui prend en compte le résultat de la requête qui permet de connaître les champs à créer.

Default
,

J'ai suivi un petit exemple sur le site des zéro Texte du lien sauf que j'ai ce message d'erreur

Expected argument of type "Doctrine\ORM\QueryBuilder", "Doctrine\ORM\Query" given

Avez vous une idée svp??

Mon code source est ici Texte du lien