我几个月前能够让这个工作正常运行。虽然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 功能代码。标准的 Ajax 包括以下内容:
3.1> -- 在控制器中创建一个用于处理 Ajax 请求的操作。
主要想要获取与特定标签对应的类别 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> -- 在YourBundle/Resources/config/services.yml
文件中定义一个新的控制器,并告诉你的管理员服务使用这个新创建的控制器,而不是默认的CRUDController。
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]
请注意,第三个参数是您的控制器的名称。默认情况下它将是null。
3.3-在您的控制器中创建一个名为getCategoryOptionsFromTagAction的操作。您的Ajax调用将针对此操作。
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());
primaryTag.change();
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:如何获取添加到所有Sonata元素的唯一ID
解决方案:使用admin变量,它将使您可以访问所有Admin类属性,包括uniqId。请参阅代码以了解如何使用它。
提示 2:如何在JS中获取路由器。
解决方案:默认情况下,Symfony2 Routing在JS中无法运行。您需要使用一个名为FOSJSRouting的bundle(如上所述)并公开该路线。这将使您也可以在JS中访问路由器对象。
我稍微修改了我的解决方案,以使此示例更清晰。如果您注意到任何错误,请随时评论。
$collection->add('addToGroup', $this->getRouterIdParameter().'/addToGroup');
,然后在ajax url中使用这个路由,例如:url: '{{ admin.generateUrl('addToGroup', {'id': object.id}) }}'
,并在ajax定义中使用额外的数据参数:data: 'group='+$(this).prevAll('.group-id').val()'
。 - lopsidedMerchantAdmin::getEditTemplate()
م€‚وˆ‘ه؟…é،»ه°†ه…¶و›´و”¹ن¸؛MerchantAdmin::getTemplate($name)
,ه¹¶هœ¨$name === 'edit'
و—¶è؟”ه›وˆ‘çڑ„è‡ھه®ڑن¹‰و¨،و؟م€‚ - caponicadata: 'group='+$(this).prevAll('.group-id').val()
我不明白这里发生了什么。可以请您解释一下吗? - Jack Brummer