@@ -598,6 +598,20 @@ the label, errors and HTML form widget of each field inside a ``div`` tag
598
598
by default. In the :ref: `form-theming ` section, you'll learn how the ``form_row ``
599
599
output can be customized on many different levels.
600
600
601
+ .. tip ::
602
+
603
+ You can access the current data of your form via ``form.vars.value ``:
604
+
605
+ .. configuration-block ::
606
+
607
+ .. code-block :: jinja
608
+
609
+ {{ form.vars.value.task }}
610
+
611
+ .. code-block :: html+php
612
+
613
+ <?php echo $view['form']->get('value')->getTask() ?>
614
+
601
615
.. index ::
602
616
single: Forms; Rendering each field by hand
603
617
@@ -746,6 +760,8 @@ Placing the form logic into its own class means that the form can be easily
746
760
reused elsewhere in your project. This is the best way to create forms, but
747
761
the choice is ultimately up to you.
748
762
763
+ .. _book-forms-data-class :
764
+
749
765
.. sidebar :: Setting the ``data_class``
750
766
751
767
Every form needs to know the name of the class that holds the underlying
@@ -936,9 +952,12 @@ and can be persisted to the database or used however you need.
936
952
Embedding a Collection of Forms
937
953
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
938
954
939
- You can also embed a collection of forms into one form. This is done by
940
- using the ``collection `` field type. For more information, see the
941
- :doc: `collection field type reference</reference/forms/types/collection> `.
955
+ You can also embed a collection of forms into one form (imagine a ``Category ``
956
+ form with many ``Product `` sub-forms). This is done by using the ``collection ``
957
+ field type.
958
+
959
+ For more information see the ":doc: `/cookbook/form/form_collections `" cookbook
960
+ entry and the :ref: `collection</reference/forms/types/collection> ` field type reference.
942
961
943
962
.. index ::
944
963
single: Forms; Theming
@@ -1295,6 +1314,130 @@ section.
1295
1314
The ``intention `` option is optional but greatly enhances the security of
1296
1315
the generated token by making it different for each form.
1297
1316
1317
+ .. index:
1318
+ single: Forms; With no class
1319
+
1320
+ Using a Form without a Class
1321
+ ----------------------------
1322
+
1323
+ In most cases, a form is tied to an object, and the fields of the form get
1324
+ and store their data on the properties of that object. This is exactly what
1325
+ you've seen so far in this chapter with the `Task ` class.
1326
+
1327
+ But sometimes, you may just want to use a form without a class, and get back
1328
+ an array of the submitted data. This is actually really easy::
1329
+
1330
+ // make sure you've imported the Request namespace above the class
1331
+ use Symfony\Component\HttpFoundation\Request
1332
+ // ...
1333
+
1334
+ public function contactAction(Request $request)
1335
+ {
1336
+ $defaultData = array('message' => 'Type your message here');
1337
+ $form = $this->createFormBuilder($defaultData)
1338
+ ->add('name', 'text')
1339
+ ->add('email', 'email')
1340
+ ->add('message', 'textarea')
1341
+ ->getForm();
1342
+
1343
+ if ($request->getMethod() == 'POST') {
1344
+ $form->bindRequest($request);
1345
+
1346
+ // data is an array with "name", "email", and "message" keys
1347
+ $data = $form->getData();
1348
+ }
1349
+
1350
+ // ... render the form
1351
+ }
1352
+
1353
+ By default, a form actually assumes that you want to work with arrays of
1354
+ data, instead of an object. There are exactly two ways that you can change
1355
+ this behavior and tie the form to an object instead:
1356
+
1357
+ 1. Pass an object when creating the form (as the first argument to ``createFormBuilder ``
1358
+ or the second argument to ``createForm ``);
1359
+
1360
+ 2. Declare the ``data_class `` option on your form.
1361
+
1362
+ If you *don't * do either of these, then the form will return the data as
1363
+ an array. In this example, since ``$defaultData `` is not an object (and
1364
+ no ``data_class `` option is set), ``$form->getData() `` ultimately returns
1365
+ an array.
1366
+
1367
+ .. tip ::
1368
+
1369
+ You can also access POST values (in this case "name") directly through
1370
+ the request object, like so:
1371
+
1372
+ .. code-block :: php
1373
+
1374
+ $this->get('request')->request->get('name');
1375
+
1376
+ Be advised, however, that in most cases using the getData() method is
1377
+ a better choice, since it returns the data (usually an object) after
1378
+ it's been transformed by the form framework.
1379
+
1380
+ Adding Validation
1381
+ ~~~~~~~~~~~~~~~~~
1382
+
1383
+ The only missing piece is validation. Usually, when you call ``$form->isValid() ``,
1384
+ the object is validated by reading the constraints that you applied to that
1385
+ class. But without a class, how can you add constraints to the data of your
1386
+ form?
1387
+
1388
+ The answer is to setup the constraints yourself, and pass them into your
1389
+ form. The overall approach is covered a bit more in the :ref: `validation chapter<book-validation-raw-values> `,
1390
+ but here's a short example::
1391
+
1392
+ // import the namespaces above your controller class
1393
+ use Symfony\Component\Validator\Constraints\Email;
1394
+ use Symfony\Component\Validator\Constraints\MinLength;
1395
+ use Symfony\Component\Validator\Constraints\Collection;
1396
+
1397
+ $collectionConstraint = new Collection(array(
1398
+ 'name' => new MinLength(5),
1399
+ 'email' => new Email(array('message' => 'Invalid email address')),
1400
+ ));
1401
+
1402
+ // create a form, no default values, pass in the constraint option
1403
+ $form = $this->createFormBuilder(null, array(
1404
+ 'validation_constraint' => $collectionConstraint,
1405
+ ))->add('email', 'email')
1406
+ // ...
1407
+ ;
1408
+
1409
+ Now, when you call `$form->isValid() `, the constraints setup here are run
1410
+ against your form's data. If you're using a form class, override the ``getDefaultOptions ``
1411
+ method to specify the option::
1412
+
1413
+ namespace Acme\TaskBundle\Form\Type;
1414
+
1415
+ use Symfony\Component\Form\AbstractType;
1416
+ use Symfony\Component\Form\FormBuilder;
1417
+ use Symfony\Component\Validator\Constraints\Email;
1418
+ use Symfony\Component\Validator\Constraints\MinLength;
1419
+ use Symfony\Component\Validator\Constraints\Collection;
1420
+
1421
+ class ContactType extends AbstractType
1422
+ {
1423
+ // ...
1424
+
1425
+ public function getDefaultOptions(array $options)
1426
+ {
1427
+ $collectionConstraint = new Collection(array(
1428
+ 'name' => new MinLength(5),
1429
+ 'email' => new Email(array('message' => 'Invalid email address')),
1430
+ ));
1431
+
1432
+ $options['validation_constraint'] = $collectionConstraint;
1433
+ }
1434
+ }
1435
+
1436
+ Now, you have the flexibility to create forms - with validation - that return
1437
+ an array of data, instead of an object. In most cases, it's better - and
1438
+ certainly more robust - to bind your form to an object. But for simple forms,
1439
+ this is a great approach.
1440
+
1298
1441
Final Thoughts
1299
1442
--------------
1300
1443
@@ -1320,6 +1463,7 @@ Learn more from the Cookbook
1320
1463
* :doc: `File Field Reference </reference/forms/types/file >`
1321
1464
* :doc: `Creating Custom Field Types </cookbook/form/create_custom_field_type >`
1322
1465
* :doc: `/cookbook/form/form_customization `
1466
+ * :doc: `/cookbook/form/dynamic_form_generation `
1323
1467
1324
1468
.. _`Symfony2 Form Component` : https://github.com/symfony/Form
1325
1469
.. _`DateTime` : http://php.net/manual/en/class.datetime.php
0 commit comments