Symfony formbuilder met JQueryUI Sortable
Ik wil graag een formulier maken waarin checkboxen toegevoegd/bewerkt/verwijderd kunnen worden en ook nog eens op willekeurige volgorde gezet kunnen worden Met Symfony's "formbuilder" en JQueryUI Sortable. Deze checkbox-collectie wordt dan later in een ander formulier voor de eindgebruiker geplaatst. zoiets dus
Ik heb een Entity genaamd FlexOption. Deze Entity staat zeg maar voor één checkbox.
Daarna heb ik rechtstreeks in mijn Controller een Form aangemaakt met slechts één formType namelijk het type collection. Rechtstreeks in de controller omdat ik geen Entity nodig heb. Ik weet even niet zo goed te verwoorden waarom ik die niet nodig heb.. maar het komt er op neer dat er slechts één lijst met FlexOptions zal bestaan er hoeft dus geen one-to-many in de database te komen.
De controller:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('MainBundle:FlexOption')->findAll();
$defaultData = array();
$form = $this->createFormBuilder($defaultData)
->add('options', 'collection', array(
'type' => new \MainBundle\Form\FlexOptionType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'data' => $entities,
))
->add('Verzenden', 'submit')
->getForm();
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
print_r($form->getData());
exit;
}
}
return array(
'form' => $form->createView(),
);
}
?>
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('MainBundle:FlexOption')->findAll();
$defaultData = array();
$form = $this->createFormBuilder($defaultData)
->add('options', 'collection', array(
'type' => new \MainBundle\Form\FlexOptionType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'data' => $entities,
))
->add('Verzenden', 'submit')
->getForm();
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
print_r($form->getData());
exit;
}
}
return array(
'form' => $form->createView(),
);
}
?>
Na het verzenden en Validatie haal ik de gegevens op met $form->getData(). Het resultaat is een array als hieronder:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Array
(
[options] => Array
(
[0] => MainBundle\Entity\FlexOption Object
(
[id:MainBundle\Entity\FlexOption:private] => 3
[label:MainBundle\Entity\FlexOption:private] => test
[sequence:MainBundle\Entity\FlexOption:private] => 0
[deleted:MainBundle\Entity\FlexOption:private] =>
)
[1] => MainBundle\Entity\FlexOption Object
(
[id:MainBundle\Entity\FlexOption:private] => 1
[label:MainBundle\Entity\FlexOption:private] => Film / Fotografie
[sequence:MainBundle\Entity\FlexOption:private] => 1
[deleted:MainBundle\Entity\FlexOption:private] =>
)
)
)
(
[options] => Array
(
[0] => MainBundle\Entity\FlexOption Object
(
[id:MainBundle\Entity\FlexOption:private] => 3
[label:MainBundle\Entity\FlexOption:private] => test
[sequence:MainBundle\Entity\FlexOption:private] => 0
[deleted:MainBundle\Entity\FlexOption:private] =>
)
[1] => MainBundle\Entity\FlexOption Object
(
[id:MainBundle\Entity\FlexOption:private] => 1
[label:MainBundle\Entity\FlexOption:private] => Film / Fotografie
[sequence:MainBundle\Entity\FlexOption:private] => 1
[deleted:MainBundle\Entity\FlexOption:private] =>
)
)
)
Nu Moet ik deze array dus weer in (een ArrayCollection van) FlexOption objecten zien te zetten.
Ik vermoed dat ik Serializer->denormalize() aan de slag moet?
Wie kan mij een duwtje in de goede richting geven?
Alvast bedankt,
Frank
Gewijzigd op 17/02/2015 00:01:07 door Frank Nietbelangrijk
Het is inmiddels op een andere manier opgelost maar de vraag is nog niet beantwoord.
Gewijzigd op 30/03/2015 09:16:02 door Frank Nietbelangrijk
* Form#bind() is deprecated, gebruik Form#bindRequest()
* De request method check gebeurd in Form#isSubmitted(), welke gecalled wordt in Form#isValid(). Het is niet nodig om dit zelf te controleren. De method kun je aanpassen met de 'method' form option
Je controller wordt dan iets als:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('MainBundle:FlexOption')->findAll();
$defaultData = array();
$form = $this->createFormBuilder($defaultData)
// ...
->getForm();
$form->bindRequest($request);
// de isSubmitted() call is niet nodig, maar de best practices
// raden aan het er wel in te voegen, om je code beter leesbaar te maken
if ($form->isSubmitted() && $form->isValid()) {
// waarom eigenlijk niet $form->get('options')->getData() ?
print_r($form->getData();
}
return array('form' => $form->createView());
}
?>
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('MainBundle:FlexOption')->findAll();
$defaultData = array();
$form = $this->createFormBuilder($defaultData)
// ...
->getForm();
$form->bindRequest($request);
// de isSubmitted() call is niet nodig, maar de best practices
// raden aan het er wel in te voegen, om je code beter leesbaar te maken
if ($form->isSubmitted() && $form->isValid()) {
// waarom eigenlijk niet $form->get('options')->getData() ?
print_r($form->getData();
}
return array('form' => $form->createView());
}
?>
De rede dat je geen ArrayCollection terug krijgt is eigenlijk vrij simpel: Je gebruikt nergens een array collection. ObjectRepository#findAll() returned namelijk een array: https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/Persistence/ObjectRepository.php#L41-46
Je kan een array overigens vrij makkelijk in een ArrayCollection omzetten:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
use Doctrine\Common\Collections\ArrayCollection;
// ...
$collection = new ArrayCollection($form->getData());
?>
use Doctrine\Common\Collections\ArrayCollection;
// ...
$collection = new ArrayCollection($form->getData());
?>
Het mooiste is om dit in een form data transformer te stoppen (View -> Norm).
Als eerste ontzettend bedankt voor je reactie wederom.
Ik heb nog niet alles bestudeerd uit je bericht maar kan het zijn dat het handleRequest() moet zijn in plaats van bindRequest() ? Op die laatste krijg ik namelijk een foutmelding. Ik gebruik Symfony 2.6.
Toevoeging op 30/03/2015 13:32:36:
Oké je kan dus gewoon een array meegeven aan de constructor van ArrayCollection.
>> Het mooiste is om dit in een form data transformer te stoppen (View -> Norm).
Ik zie met behulp van Google dat daar informatie over te vinden is. Hiermee kan ik bovengenoemde data omzetten naar een gewone array of een arrayCollection?
Inderdaad, typefoutje :)
>> Hiermee kan ik bovengenoemde data omzetten naar een gewone array of een arrayCollection?
Data transformers zijn een mooie en abstracte manier om waardes om te zetten. Elk form element heeft View data (het geen voor HTML gebruikt wordt), Norm data (normalized, het geen binnen de form gebruikt wordt) en Model data (de waarde die je entity/document/model krijgt). In het geval van een date form is de view data een array met dag, maand en jaar, de norm data een DateTime object en de model data bijv. een YYYY-MM-DD string.
Zodra je je form uit je controller haalt en er een form type van maakt zou ik aanraden om data transformers te gebruiken. Overigens een talk van de maker van de Form component over data transformers: https://www.youtube.com/watch?v=Q80b9XeLUEA
I owe you a beer..