2017-05-10 7 views
1

Je veux créer un formulaire qui sert à ajouter, éditer (et supprimer lorsque le champ url est vide). Le problème est que le nombre de lignes/éléments est variable. (Comme vous pouvez le voir sur la première photo)Symfony - formulaires avec nombre variable de champs

Questions:

1) Comment écrire une forme qui a un nombre variable de champs.

2) Comment analyser les données dans les champs de ce formulaire.

class GalleryType extends AbstractType { 

public function buildForm(FormBuilderInterface $builder, array $options) { 
    $builder->add(
    //...some textType, fileType fields,...etc 
    ); 
} 

public function configureOptions(OptionsResolver $resolver) { 
    $resolver->setDefaults([ 
     //... 
     //some data/data_class option that parse data into the field 
    ]); 
} 

example of form (administration part)

Informations supplémentaires:

Je travaille sur propre système de gestion de contenu simple avec Symfony 3. Je souhaite autoriser l'utilisateur à ajouter un élément de menu avec des informations telles que: URL, Titre et, par exemple, l'icône FA, l'image de fond, etc.

-Il y a toujours une ligne vide pour l'ajout d'élément et le reste des champs sont remplis avec des données existantes (élément (s) de menu). Lorsque vous confirmez le formulaire, cette ligne est ajoutée dans le formulaire (et la ligne vide également).

-Il existe peu de type de menu différent: menu principal, curseur, menu latéral, qui a différents types de champs. (Vous pouvez le voir sur la deuxième photo)

Menu -Main a: titre, url et certains élément peut avoir des éléments enfants (comme sous-menu)

-Slider a: titre, url, couleur du titre, background image

menu -Side a: titre, url et police Impressionnant Icône

je l'ai déjà fait la forme pour le menu de navigation (pied de page) où se trouve à seulement 2 champs (titre et le lien), mais je me sens ce n'est pas proprement façon comment la programmer ... à des fins d'illustration voici comment j'ai fait la navigation example of menus design Controller:

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Symfony\Component\HttpFoundation\Request; 
use AppBundle\Entity\SMBundle\Navigation; 
use AppBundle\Entity\Sett; 
use Symfony\Component\Serializer\Serializer; 
use Symfony\Component\Serializer\Encoder\JsonEncoder; 
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; 
use Symfony\Component\Form\Extension\Core\Type\TextType; 

class SettingsController extends Controller { 

//.... 

/** 
* @Route("/admin/menu/navigation", name="navigation") 
*/ 
public function navigationAction(Request $request) { 
    $set = $this->getDoctrine()->getRepository('AppBundle:Sett')->findOneByName('navigation'); 
    $navigation = $this->deserializeFromStringToObject('navigation'); 

    if (!$navigation) { 
     $set = new Sett(); 
     $navigation = new Navigation(); 
    } 

    $form = $this->createFormFromArray($navigation->getLinksArray()); 
    $form->handleRequest($request); 

    if ($form->isSubmitted() && $form->isValid()) { 
     $set->setEditedAt(new \DateTime()); 
     $set->setName('navigation'); 

     $this->brutalHack($navigation, $form); 

     $set->setContent($this->serializeFromObjectToString($navigation)); 

     // Save 
     $this->save($set); 
     return $this->redirect($this->generateUrl('navigation')); 
    } 
    return $this->render("viewSM/menu/navigation.html.twig", array('form' => $form->createView())); 
} 

private function deserializeFromStringToObject($name) { 
    $object = $this->getDoctrine()->getRepository('AppBundle:Sett')->findOneByName($name); 
    if (!$object) { 
     return null; 
    } 
    $serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); 
    return $serializer->deserialize($object->getContent(), 'AppBundle\\Entity\\SMBundle\\' . ucfirst($name), 'json'); 
} 

private function serializeFromObjectToString($object) { 
    $serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); 
    return $serializer->serialize($object, 'json'); 
} 

    private function createFormFromArray(array $collection) { 
    $i = 0; 
    $formBuilder = $this->createFormBuilder(); 

    foreach ($collection as $key => $value) { 
     $formBuilder 
       ->add('url' . $i, TextType::class, ['label' => 'URL ', 'data' => '' . $key, 'attr' => ['class' => 'form-control']]) 
       ->add('name' . $i, TextType::class, ['label' => 'Titulek ', 'data' => '' . $value, 'attr' => ['class' => 'form-control']]); 
     $i++; 
    } 
    $formBuilder 
      ->add('url' . $i, TextType::class, ['label' => 'URL ', 'attr' => ['class' => 'form-control']]) 
      ->add('name' . $i, TextType::class, ['label' => 'Titulek ', 'attr' => ['class' => 'form-control']]) 
      ->add('submit', \Symfony\Component\Form\Extension\Core\Type\SubmitType::class, ['label' => 'Uložit', 'attr' => ['class' => 'btn btn-primary']]); 
    $form = $formBuilder->getForm(); 
    return $form; 
} 

private function save($set) { 
    $em = $this->getDoctrine()->getManager(); 
    $em->persist($set); 
    $em->flush(); 
} 

private function brutalHack($navigation, $form) { 
    $nav = array(); 
    if (count($navigation->getLinksArray()) == 0) { 
     $nav[$form['url0']->getData()] = $form['name0']->getData(); 
    } 
    for ($i = 0; $i < count($navigation->getLinksArray()); $i++) { 
     $key = $form['url' . $i]->getData(); 
     $value = $form['name' . $i]->getData(); 
     if ($key != NULL && $value != NULL) { 
      $nav[$key] = $value; 
     } 
    } 
    $key = $form['url' . $i]->getData(); 
    $value = $form['name' . $i]->getData(); 
    if ($key != NULL && $value != NULL) { 
     $nav[$key] = $value; 
    } 
    $navigation->setLinksArray($nav); 
} 
//... 
} 

Entité:

use Doctrine\ORM\Mapping as ORM; 

/** 
* @ORM\Entity 
* @ORM\Table(name="sett") 
* @ORM\HasLifecycleCallbacks 
*/ 
class Sett 
{ 
/** 
* @ORM\Id 
* @ORM\Column(type="integer") 
* @ORM\GeneratedValue(strategy="AUTO") 
*/ 
private $id; 

/** 
* @ORM\Column(name="name", length=255) 
*/ 
private $name; 

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

    /** 
* @ORM\Column(name="edited_at", type="datetime") 
*/ 
private $editedAt; 

/** 
* @ORM\Column(name="created_at", type="datetime") 
*/ 
private $createdAt; 

/** 
* @ORM\PrePersist 
*/ 
public function onPrePersist() 
{ 
    $this->createdAt = new \DateTime(); 
} 

/** 
* Get id 
* 
* @return integer 
*/ 
public function getId() 
{ 
    return $this->id; 
} 

/** 
* Set name 
* 
* @param string $name 
* 
* @return Set 
*/ 
public function setName($name) 
{ 
    $this->name = $name; 

    return $this; 
} 

/** 
* Get name 
* 
* @return string 
*/ 
public function getName() 
{ 
    return $this->name; 
} 

/** 
* Set content 
* 
* @param array $content 
* 
* @return Set 
*/ 
public function setContent($content) 
{ 
    $this->content = $content; 

    return $this; 
} 

/** 
* Get content 
* 
* @return array 
*/ 
public function getContent() 
{ 
    return $this->content; 
} 

/** 
* Set editedAt 
* 
* @param \DateTime $editedAt 
* 
* @return Set 
*/ 
public function setEditedAt($editedAt) 
{ 
    $this->editedAt = $editedAt; 

    return $this; 
} 

/** 
* Get editedAt 
* 
* @return \DateTime 
*/ 
public function getEditedAt() 
{ 
    return $this->editedAt; 
} 

/** 
* Set createdAt 
* 
* @param \DateTime $createdAt 
* 
* @return Set 
*/ 
public function setCreatedAt($createdAt) 
{ 
    $this->createdAt = $createdAt; 

    return $this; 
} 

/** 
* Get createdAt 
* 
* @return \DateTime 
*/ 
public function getCreatedAt() 
{ 
    return $this->createdAt; 
} 
} 

Classe de données:

class Navigation 
{ 
    private $linksArray; 

public function __construct() { 
    $this->linksArray=array(); 
} 

function getLinksArray() { 
    return $this->linksArray; 
} 

function setLinksArray($linksArray) { 
    $this->linksArray = $linksArray; 
} 

function add($key,$value){ 
    $this->linksArray[$key]=$value; 
} 


} 

Répondre

1

Je ne sais pas si cela va fonctionner, mais vous devriez essayer.

2) Comment analyser les données dans le formulaire qui a un nombre variable de champs.

Vous pouvez envoyer les données sous forme d'options $.

dans votre contrôleur

$oForm = $this->createForm(YourFormType::class, 
$FormObject, [ 
    'your_options' => [ 
     'Checkbox' => 'FieldName1', 
     'TextArea' => 'FieldName2' 
]); 

dans votre formulaire

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 

foreach($options['your_options'] as $key, $option) { //you can name $option as $filedName or whatever you find convenient 
    $builder->add($option, $key.Type::class); 
} 
...} 


public function configureOptions(OptionsResolver $resolver) 
{ 
    $resolver->setDefaults([ 
     'your_options' => null 
    ]) 
} 
+0

array $ options est $ your_options ??? –

+0

oui. j'ai mis à jour la réponse –