GitHub PullRequestReviewCommentEvent at 2014-01-09 16:25:35
Repository: symfony-docs
Actor: weaverryan
Payload: {"comment":{"url":"https://api.github.com/repos/symfony/symfony-docs/pulls/comments/8761323","id":8761323,"diff_hunk":"@@ -581,17 +599,170 @@ The type would now look like::\n                 }\n             );\n         }\n+\n+        // ...\n     }\n \n-You can see that you need to listen on these two events and have different callbacks\n-only because in two different scenarios, the data that you can use is available in different events.\n-Other than that, the listeners always perform exactly the same things on a given form.\n+You can see that you need to listen on these two events and have different\n+callbacks only because in two different scenarios, the data that you can use is\n+available in different events. Other than that, the listeners always perform\n+exactly the same things on a given form.\n \n-One piece that may still be missing is the client-side updating of your form\n-after the sport is selected. This should be handled by making an AJAX call\n-back to your application. In that controller, you can submit your form, but\n-instead of processing it, simply use the submitted form to render the updated\n-fields. The response from the AJAX call can then be used to update the view.\n+One piece that is still missing is the client-side updating of your form after\n+the sport is selected. This should be handled by making an AJAX call back to\n+your application. Assume that you have a sport meetup creation controller::\n+\n+    // src/Acme/DemoBundle/Controller/MeetupController.php\n+    namespace Acme\\DemoBundle\\Controller;\n+\n+    use Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller;\n+    use Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Route;\n+    use Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Template;\n+    use Symfony\\Component\\HttpFoundation\\Request;\n+    use Acme\\DemoBundle\\Entity\\SportMeetup;\n+    use Acme\\DemoBundle\\Form\\Type\\SportMeetupType;\n+    // ...\n+\n+    /**\n+     * @Route(\"/meetup\")\n+     */\n+    class MeetupController extends Controller\n+    {\n+        /**\n+         * @Route(\"/create\", name=\"meetup_create\")\n+         * @Template\n+         */\n+        public function createAction(Request $request)\n+        {\n+            $meetup = new SportMeetup();\n+            $form = $this->createForm(new SportMeetupType(), $meetup);\n+            $form->handleRequest($request);\n+            if ($form->isValid()) {\n+                // ... save the meetup, redirect etc.\n+            }\n+\n+            return array('form' => $form->createView());\n+        }\n+\n+        // ...\n+    }\n+\n+The associated template uses some JavaScript to update the ``position`` form\n+field according to the current selection in the ``sport`` field. To ease things\n+it makes use of `jQuery`_ library and the `FOSJsRoutingBundle`_:\n+\n+.. configuration-block::\n+\n+    .. code-block:: html+jinja\n+\n+        {# src/Acme/DemoBundle/Resources/views/Meetup/create.html.twig #}\n+        {{ form_start(form) }}\n+            {{ form_row(form.sport) }}    {# <select id=\"meetup_sport\" ... #}\n+            {{ form_row(form.position) }} {# <select id=\"meetup_position\" ... #}\n+            {# ... #}\n+        {{ form_end(form) }}\n+\n+        {# ... Include jQuery and scripts from FOSJsRoutingBundle ... #}\n+        <script>\n+        $(function(){\n+            // When sport gets selected ...\n+            $('#meetup_sport').change(function(){\n+                var $position = $('#meetup_position');\n+                // Remove current position options except first \"empty_value\" option\n+                $position.find('option:not(:first)').remove();\n+                var sportId = $(this).val();\n+                if (sportId) {\n+                    // Issue AJAX call fetching positions for selected sport as JSON\n+                    $.getJSON(\n+                        // FOSJsRoutingBundle generates route including selected sport ID\n+                        Routing.generate('meetup_positions_by_sport', {id: sportId}),\n+                        function(positions) {\n+                            // Append fetched positions associated with selected sport\n+                            $.each(positions, function(key, position){\n+                                $position.append(new Option(position[1], position[0]));\n+                            });\n+                        }\n+                    );\n+                }\n+            });\n+        });\n+        </script>\n+\n+    .. code-block:: html+php\n+\n+        <!-- src/Acme/DemoBundle/Resources/views/Meetup/create.html.php -->\n+        <?php echo $view['form']->start($form) ?>\n+            <?php echo $view['form']->row($form['sport']) ?>    <!-- <select id=\"meetup_sport\" ... -->\n+            <?php echo $view['form']->row($form['position']) ?> <!-- <select id=\"meetup_position\" ... -->\n+            <!-- ... -->\n+        <?php echo $view['form']->end($form) ?>\n+\n+        <!-- ... Include jQuery and scripts from FOSJsRoutingBundle ... -->\n+        <script>\n+        $(function(){\n+            // When sport gets selected ...\n+            $('#meetup_sport').change(function(){\n+                var $position = $('#meetup_position');\n+                // Remove current position options except first \"empty_value\" option\n+                $position.find('option:not(:first)').remove();\n+                var sportId = $(this).val();\n+                if (sportId) {\n+                    // Issue AJAX call fetching positions for selected sport as JSON\n+                    $.getJSON(\n+                        // FOSJsRoutingBundle generates route including selected sport ID\n+                        Routing.generate('meetup_positions_by_sport', {id: sportId}),\n+                        function(positions) {\n+                            // Append fetched positions associated with selected sport\n+                            $.each(positions, function(key, position){\n+                                $position.append(new Option(position[1], position[0]));\n+                            });\n+                        }\n+                    );\n+                }\n+            });\n+        });\n+        </script>\n+\n+The last piece is implementing a controller for the\n+``meetup_positions_by_sport`` route returning the positions as JSON according\n+to the currently selected sport. To ease things again the controller makes use\n+of the :doc:`@ParamConverter </bundles/SensioFrameworkExtraBundle/annotations/converters>`\n+listener to convert the submitted sport ID into a ``Sport`` object::","path":"cookbook/form/dynamic_form_modification.rst","position":216,"original_position":216,"commit_id":"3b4f89ee81d74d3bbeabde6fad0d3b9841f806ec","original_commit_id":"3b4f89ee81d74d3bbeabde6fad0d3b9841f806ec","user":{"login":"weaverryan","id":121003,"avatar_url":"https://gravatar.com/avatar/681e6d4d4cf91760e5e1d8ac9d6d7fc4?d=https%3A%2F%2Fidenticons.github.com%2Fc85fe06b7f6e1c28c57403b6773088f9.png&r=x","gravatar_id":"681e6d4d4cf91760e5e1d8ac9d6d7fc4","url":"https://api.github.com/users/weaverryan","html_url":"https://github.com/weaverryan","followers_url":"https://api.github.com/users/weaverryan/followers","following_url":"https://api.github.com/users/weaverryan/following{/other_user}","gists_url":"https://api.github.com/users/weaverryan/gists{/gist_id}","starred_url":"https://api.github.com/users/weaverryan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weaverryan/subscriptions","organizations_url":"https://api.github.com/users/weaverryan/orgs","repos_url":"https://api.github.com/users/weaverryan/repos","events_url":"https://api.github.com/users/weaverryan/events{/privacy}","received_events_url":"https://api.github.com/users/weaverryan/received_events","type":"User","site_admin":false},"body":"I'm a little -1 on using the ParamConverter here","created_at":"2014-01-09T16:25:35Z","updated_at":"2014-01-09T16:25:35Z","html_url":"https://github.com/symfony/symfony-docs/pull/3411#discussion_r8761323","pull_request_url":"https://api.github.com/repos/symfony/symfony-docs/pulls/3411","_links":{"self":{"href":"https://api.github.com/repos/symfony/symfony-docs/pulls/comments/8761323"},"html":{"href":"https://github.com/symfony/symfony-docs/pull/3411#discussion_r8761323"},"pull_request":{"href":"https://api.github.com/repos/symfony/symfony-docs/pulls/3411"}}}}