¿Cómo usar Ajax en los formularios de Sonata Admin?

Tengo una entidad mercantil con los siguientes campos y asociaciones:

/** * @ORM\ManyToMany(targetEntity="Category", inversedBy="merchants") */ public $categories; /** * @ORM\ManyToMany(targetEntity="Tag", inversedBy="merchants") */ public $tags; /** * @ORM\ManyToOne(targetEntity="Category", inversedBy="merchants") */ protected $primaryCategory; /** * @ORM\ManyToOne(targetEntity="Tag", inversedBy="merchants") */ protected $primaryTag; 

Las tags y categorías también tienen un mapeo ManyToMany. Así que tenemos las tablas de asignación Tag_Category, Merchant_Tag, Merchant_Category.

Ahora quiero realizar algunos ajax en estos campos.

Quiero permitir que el usuario seleccione primero la Etiqueta primaria. Sobre la base de la etiqueta primaria, ajax actualiza las categorías solo a aquellas que pertenecen a esta etiqueta y algunas operaciones más.

¿Cómo puedo conseguir esto?

¡Gracias!

Pude hacer esto funcionar hace unos meses. Si bien lo que a.aitboudad ha compartido es exacto. Hay algunos problemas que los primeros tiempos con Symfony / Sonata podrían enfrentar.

Aquí están los pasos.

1> Extienda el edit.html.twig / base_edit.html.twig Sonata CRUD. Para simplificar, usaré solo el último. Copie el vendor/bundles/Sonata/AdminBundle/Resources/views/CRUD/base_edit.html.twig en la carpeta de vistas correspondiente a MerchantAdminController – YourBundle/Resources/views/Merchant/base_edit.html.twig

2> Necesitamos decirle a nuestra clase MerchantAdmin que use esta plantilla. Así que reemplazamos el método getEditTemplate de getEditTemplate así:

 public function getEditTemplate() { return 'YourBundle:Merchant:base_edit.html.twig'; } 

3> Luego tenemos que codificar la funcionalidad de Ajax en nuestro base_edit.html.twig . Standard Ajax se compone de lo siguiente:

3.1> – Crear una acción en el controlador para la solicitud de Ajax Principalmente queremos obtener una lista de ID de categoría correspondiente a una etiqueta en particular. Pero lo más probable es que solo estés usando el Controlador CRUD de Sonata.

Defina su MerchantAdminController que extiende CRUDController

  

3.2> - Indique a su servicio de administración que use este controlador recién creado en lugar del controlador CRUD predeterminado definiéndolo en YourBundle/Resources/config/services.yml

 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] 

Tenga en cuenta que el tercer argumento es el nombre de su controlador. Por defecto, habría sido nulo.

3.3> - Crea una acción llamada getCategoryOptionsFromTagAction en tu controlador. Su llamada Ajax será a esta Acción.

 // route - get_categories_from_tag public function getCategoryOptionsFromTagAction($tagId) { $html = ""; // HTML as response $tag = $this->getDoctrine() ->getRepository('YourBundle:Tag') ->find($tagId); $categories = $tag->getCategories(); foreach($categories as $cat){ $html .= ''; } return new Response($html, 200); } 

3.4> - Crea la ruta correspondiente en app/config/routing.yml . Recuerde exponer su ruta si está utilizando FOSJsRoutingBundle (de lo contrario, tendrá que codificar, lo que no es una buena idea).

 get_categories_from_tag: pattern: /{_locale}/admin/gd/admin/merchant/get-categories-from-tag/{tagId} defaults: {_controller: GDAdminBundle:MerchantAdmin:getCategoryOptionsFromTag} options: expose: true 

3.5> - Haz la Solicitud Ajax y usa la respuesta

 {% block javascripts %} {{ parent() }}  {% endblock %} 

Gotcha 1: cómo obtener la identificación única que se agrega a todos los elementos de Sonata

Solución: utilice la variable de administrador que le dará acceso a todas las propiedades de la clase de administración, incluido uniqId. Vea el código sobre cómo usarlo.

Gotcha 2: Cómo obtener el enrutador en tu JS.

Solución: de manera predeterminada, el enrutamiento Symfony2 no funciona en JS. Debe usar un paquete llamado FOSJSRouting (explicado anteriormente) y exponer la ruta. Esto le dará acceso al objeto Router dentro de su JS también.

He modificado mi solución ligeramente para hacer que este ejemplo sea más claro. Si nota algo incorrecto, no dude en comentar.

En el paso 1 de la respuesta de Amit y Lumbendil debes cambiar

 {% extends base_template %} 

dentro

 {% extends 'SonataAdminBundle::standard_layout.html.twig' %} 

si obtiene un error como

 Unable to find template "" in YourBundle:YourObject:base_edit.html.twig at line 34. 

Publicación muy detallada, solo para actualizar la forma de sobrescribir y usar la plantilla de edición en la clase Admin.
Ahora, deberías hacerlo de esta manera:

 // src/AppBundle/Admin/EntityAdmin.php class EntityAdmin extends Admin { public function getTemplate($name) { if ( $name == "edit" ) { // template 'base_edit.html.twig' placed in app/Resources/views/Entity return 'Entity/base_edit.html.twig' ; } return parent::getTemplate($name); } } 

O inyéctelo en la definición del servicio que utilizó el método proporcionado , para mantener la clase Admin tan limpia como sea posible:

 // app/config/services.yml app.admin.entity: class: AppBundle\Admin\EntityAdmin arguments: [~, AppBundle\Entity\Entity, ~] tags: - {name: sonata.admin, manager_type: orm, group: "Group", label: "Label"} calls: - [ setTemplate, [edit, Entity/base_edit.html.twig]] 

en los javascripts del bloque, debe cambiar "liszt:updated" por "chosen:updated"

espero que ayude a alguien;)