Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I was able to make this work a few months back. While what a.aitboudad has shared is accurate. There are a few gotcha's that first timers with Symfony/Sonata might face.</p> <p>Here are the steps. </p> <p><strong>1> Extend Sonata CRUD's <code>edit.html.twig</code> / <code>base_edit.html.twig</code> .</strong> For simplicity, I'll use only the latter. Copy <code>vendor/bundles/Sonata/AdminBundle/Resources/views/CRUD/base_edit.html.twig</code> into the views folder corresponding to the MerchantAdminController - <code>YourBundle/Resources/views/Merchant/base_edit.html.twig</code></p> <p><strong>2> We need to tell our MerchantAdmin class to use this template.</strong> So we override SonataAdmin's <code>getEditTemplate</code> method like this:</p> <pre><code>public function getEditTemplate() { return 'YourBundle:Merchant:base_edit.html.twig'; } </code></pre> <p><strong>3></strong> Next we need to <strong>code the Ajax functionality</strong> in our <code>base_edit.html.twig</code> . Standard Ajax comprises of the following: </p> <p><strong>3.1></strong> -- Create an Action in the controller for the Ajax request We primarily want to get a list of category IDs corresponding to a particular tag. But most likely you are just using Sonata's CRUD Controller. </p> <p>Define your MerchantAdminController which extends CRUDController </p> <pre><code>&lt;?php namespace GD\AdminBundle\Controller; use Sonata\AdminBundle\Controller\CRUDController as Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use GD\AdminBundle\Entity\Merchant; class MerchantAdminController extends Controller { } </code></pre> <p><strong>3.2></strong> -- Tell your Admin service to use this newly created controller instead of the default CRUDController by defining it in <code>YourBundle/Resources/config/services.yml</code></p> <pre><code>gd_admin.merchant: class: %gd_admin.merchant.class% tags: - { name: sonata.admin, manager_type: orm, group: gd_merchant, label: Merchants } arguments: [null, GD\AdminBundle\Entity\Merchant, GDAdminBundle:MerchantAdmin] </code></pre> <p>Notice that the 3rd argument is the name of your controller. By default it would have been null. </p> <p><strong>3.3></strong> -- Create an Action named <code>getCategoryOptionsFromTagAction</code> in your controller. Your Ajax call will be to this Action. </p> <pre><code>// route - get_categories_from_tag public function getCategoryOptionsFromTagAction($tagId) { $html = ""; // HTML as response $tag = $this-&gt;getDoctrine() -&gt;getRepository('YourBundle:Tag') -&gt;find($tagId); $categories = $tag-&gt;getCategories(); foreach($categories as $cat){ $html .= '&lt;option value="'.$cat-&gt;getId().'" &gt;'.$cat-&gt;getName().'&lt;/option&gt;'; } return new Response($html, 200); } </code></pre> <p><strong>3.4></strong> -- Create the corresponding route in <code>app/config/routing.yml</code>. Remember to expose your route if you are using the FOSJsRoutingBundle (else you'll have to hardcode which is not a good idea).</p> <pre><code>get_categories_from_tag: pattern: /{_locale}/admin/gd/admin/merchant/get-categories-from-tag/{tagId} defaults: {_controller: GDAdminBundle:MerchantAdmin:getCategoryOptionsFromTag} options: expose: true </code></pre> <p><strong>3.5></strong> -- Make the Ajax Request and use the response</p> <pre><code>{% block javascripts %} {{ parent() }} &lt;script type="text/javascript"&gt; $(document).ready(function(){ var primaryTag = $("#{{ admin.uniqId }}_primaryTag"); primaryTag.change(updateCategories()); // Bind the function to updateCategories primaryTag.change(); // Manual trigger to update categories in Document load. function updateCategories(){ return function () { var tagId = $("#{{ admin.uniqId }}_primaryTag option:selected").val(); var primaryCategory = $("#{{ admin.uniqId }}_primaryCategory"); primaryCategory.empty(); primaryCategory.trigger("liszt:updated"); var locale = '{{ app.request.get('_locale') }}'; var objectId = '{{ admin.id(object) }}' var url = Routing.generate('get_categories_from_tag', { '_locale': locale, 'tagId': tagId, _sonata_admin: 'gd_admin.merchant', id: objectId }); $.post(url, { tagId: tagId }, function(data){ primaryCategory.empty().append(data); primaryCategory.trigger("liszt:updated"); },"text"); primaryCategory.val("option:first").attr("selected", true); }; } }); &lt;/script&gt; {% endblock %} </code></pre> <p><em><strong>Gotcha 1:</em></strong> How to get the Unique ID that is appended to all Sonata elements</p> <p><em><strong>Solution:</em></strong> Use the admin variable which will give you access to all the Admin Class's properties including uniqId. See code on how to use it. </p> <p><em><strong>Gotcha 2:</em></strong> How to get the Router in your JS. </p> <p><em><strong>Solution:</em></strong> By default Symfony2 Routing doesn't work in JS. You need to use a bundle called FOSJSRouting (explained above) and expose the route. This will give you access to the Router object within your JS too. </p> <p>I have modified my solution slightly to make this example clearer. If you notice anything wrong, please feel free to comment. </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload