几个月前我能够完成这项工作。虽然 a.aitboudad 分享的内容是准确的。Symfony/Sonata 的初学者可能会遇到一些问题。
以下是步骤。
1> 扩展 Sonata CRUD 的edit.html.twig
/ base_edit.html.twig
。
为简单起见,我将只使用后者。复制vendor/bundles/Sonata/AdminBundle/Resources/views/CRUD/base_edit.html.twig
到与 MerchantAdminController 对应的视图文件夹中 -YourBundle/Resources/views/Merchant/base_edit.html.twig
2> 我们需要告诉 MerchantAdmin 类使用这个模板。所以我们像这样重写 SonataAdmin 的getEditTemplate
方法:
public function getEditTemplate()
{
return 'YourBundle:Merchant:base_edit.html.twig';
}
3>接下来,我们需要在base_edit.html.twig
. 标准 Ajax 包括以下内容:
3.1> -- 在控制器中为Ajax 请求创建一个Action 我们主要想得到一个与特定标签对应的类别ID 列表。但很可能你只是在使用 Sonata 的 CRUD 控制器。
定义扩展 CRUDController 的 MerchantAdminController
<?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
{
}
3.2> -- 告诉你的管理服务使用这个新创建的控制器而不是默认的 CRUDControllerYourBundle/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]
请注意,第三个参数是控制器的名称。默认情况下,它将为空。
3.3> -- 创建一个getCategoryOptionsFromTagAction
在你的控制器中命名的动作。您的 Ajax 调用将针对此操作。
// 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 .= '<option value="'.$cat->getId().'" >'.$cat->getName().'</option>';
}
return new Response($html, 200);
}
3.4> -- 在app/config/routing.yml
. 如果您使用 FOSJsRoutingBundle,请记住公开您的路线(否则您将不得不硬编码,这不是一个好主意)。
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> -- 发出 Ajax 请求并使用响应
{% block javascripts %}
{{ parent() }}
<script type="text/javascript">
$(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);
};
}
});
</script>
{% endblock %}
问题 1:如何获取附加到所有奏鸣曲元素的唯一 ID
解决方案:使用 admin 变量,它可以让您访问所有 Admin Class 的属性,包括 uniqId。请参阅有关如何使用它的代码。
问题 2:如何在 JS 中获取路由器。
解决方案:默认情况下 Symfony2 Routing 在 JS 中不起作用。您需要使用一个名为 FOSJSRouting 的包(如上所述)并公开路由。这将使您也可以访问 JS 中的 Router 对象。
我稍微修改了我的解决方案以使这个示例更清晰。如果您发现任何错误,请随时发表评论。